chore(client): translate all user-visible strings to English

Mixed-language UI was confusing — onboarding said "Why DChain / How it
works / Your keys" in English headings but feature descriptions and
CTAs were in Russian; compose's confirm dialog was Russian; feed tabs
were Russian; error messages in humanizeTxError were Russian.
Everything user-facing is now English.

Files touched (only string literals, not comments):
  app/index.tsx              onboarding slides + CTA buttons
  app/(app)/compose.tsx      composer alerts, header button, placeholder,
                             attachment-size hint
  app/(app)/feed/index.tsx   tab labels (Following/For you/Trending),
                             empty-state hints, retry button
  app/(app)/feed/[id].tsx    post detail header + stats rows (Views,
                             Likes, Size, Paid to publish, Hosted on,
                             Hashtags)
  app/(app)/feed/tag/[tag].tsx  empty-state copy
  app/(app)/profile/[address].tsx  Profile header, Follow/Following,
                             Edit, Open chat, Address, Copied, Encryption,
                             Added, Members, unknown-contact hint
  app/(app)/new-contact.tsx  Search title, placeholder, Search button,
                             empty-state hint, E2E-ready indicator,
                             Intro label + placeholder, fee-tier labels
                             (Min / Standard / Priority), Send request,
                             Insufficient-balance alert, Request-sent
                             alert
  app/(app)/requests.tsx     Notifications title, empty-state, Accept /
                             Decline buttons, decline-confirm alert,
                             "wants to add you" line
  components/SearchBar.tsx   default placeholder
  components/feed/PostCard.tsx  long-press menu (Delete post, confirm,
                             Actions / Cancel)
  components/feed/ShareSheet.tsx  sheet title, contact-search placeholder,
                             empty state, Select contacts / Send button,
                             plural helper rewritten for English
  components/chat/PostRefCard.tsx  "POST" ribbon, "photo" indicator
  lib/api.ts                 humanizeTxError (rate-limit, clock skew,
                             bad signature, 400/5xx/network-error
                             messages)
  lib/dates.ts               dateBucket now returns Today/Yesterday/
                             "Jun 17, 2025"; month array switched to
                             English short forms

Code comments left in Russian intentionally — they're developer
context, not user-facing. This commit is purely display-string.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
vsecoder
2026-04-18 23:39:38 +03:00
parent 060ac6c2c9
commit f7a849ddcb
14 changed files with 134 additions and 139 deletions

View File

@@ -18,7 +18,7 @@ export interface SearchBarProps {
}
export function SearchBar({
value, onChangeText, placeholder = 'Поиск', autoFocus, onSubmitEditing, onClear,
value, onChangeText, placeholder = 'Search', autoFocus, onSubmitEditing, onClear,
}: SearchBarProps) {
return (
<View

View File

@@ -90,7 +90,7 @@ export function PostRefCard({ postID, author, excerpt, hasImage, own }: PostRefC
letterSpacing: 1.2,
}}
>
ПОСТ
POST
</Text>
</View>
@@ -132,7 +132,7 @@ export function PostRefCard({ postID, author, excerpt, hasImage, own }: PostRefC
>
<Ionicons name="image-outline" size={11} color={subColor} />
<Text style={{ color: subColor, fontSize: 11 }}>
с фото
photo
</Text>
</View>
)}

View File

@@ -109,7 +109,7 @@ function PostCardInner({ post, likedByMe, onStatsChanged, onDeleted, compact }:
// Roll back optimistic update.
setLocalLiked(wasLiked);
setLocalLikeCount(c => c + (wasLiked ? 1 : -1));
Alert.alert('Не удалось', String(e?.message ?? e));
Alert.alert('Failed', String(e?.message ?? e));
} finally {
setBusy(false);
}
@@ -128,13 +128,13 @@ function PostCardInner({ post, likedByMe, onStatsChanged, onDeleted, compact }:
const options: Array<{ label: string; destructive?: boolean; onPress: () => void }> = [];
if (mine) {
options.push({
label: 'Удалить пост',
label: 'Delete post',
destructive: true,
onPress: () => {
Alert.alert('Удалить пост?', 'Это действие нельзя отменить.', [
{ text: 'Отмена', style: 'cancel' },
Alert.alert('Delete post?', 'This action cannot be undone.', [
{ text: 'Cancel', style: 'cancel' },
{
text: 'Удалить',
text: 'Delete',
style: 'destructive',
onPress: async () => {
try {
@@ -145,7 +145,7 @@ function PostCardInner({ post, likedByMe, onStatsChanged, onDeleted, compact }:
});
onDeleted?.(post.post_id);
} catch (e: any) {
Alert.alert('Ошибка', String(e?.message ?? e));
Alert.alert('Error', String(e?.message ?? e));
}
},
},
@@ -160,9 +160,9 @@ function PostCardInner({ post, likedByMe, onStatsChanged, onDeleted, compact }:
style: (o.destructive ? 'destructive' : 'default') as 'default' | 'destructive',
onPress: o.onPress,
})),
{ text: 'Отмена', style: 'cancel' as const },
{ text: 'Cancel', style: 'cancel' as const },
];
Alert.alert('Действия', '', buttons);
Alert.alert('Actions', '', buttons);
}, [keyFile, mine, post.post_id, onDeleted]);
// Attachment preview URL — native Image can stream straight from the

View File

@@ -74,14 +74,14 @@ export function ShareSheet({ visible, post, onClose }: ShareSheetProps) {
post, contacts: targets, keyFile,
});
if (failed > 0) {
Alert.alert('Готово', `Отправлено в ${ok} из ${ok + failed} чат${plural(ok + failed)}.`);
Alert.alert('Done', `Sent to ${ok} of ${ok + failed} ${plural(ok + failed)}.`);
}
// Close + reset regardless — done is done.
setPicked(new Set());
setQuery('');
onClose();
} catch (e: any) {
Alert.alert('Не удалось', String(e?.message ?? e));
Alert.alert('Failed', String(e?.message ?? e));
} finally {
setSending(false);
}
@@ -136,7 +136,7 @@ export function ShareSheet({ visible, post, onClose }: ShareSheetProps) {
paddingHorizontal: 16, marginBottom: 10,
}}>
<Text style={{ color: '#ffffff', fontSize: 17, fontWeight: '700' }}>
Поделиться постом
Share post
</Text>
<View style={{ flex: 1 }} />
<Pressable onPress={closeAndReset} hitSlop={8}>
@@ -158,7 +158,7 @@ export function ShareSheet({ visible, post, onClose }: ShareSheetProps) {
<TextInput
value={query}
onChangeText={setQuery}
placeholder="Поиск по контактам"
placeholder="Search contacts"
placeholderTextColor="#5a5a5a"
style={{
flex: 1,
@@ -196,8 +196,8 @@ export function ShareSheet({ visible, post, onClose }: ShareSheetProps) {
<Ionicons name="people-outline" size={28} color="#5a5a5a" />
<Text style={{ color: '#8b8b8b', fontSize: 13, marginTop: 10 }}>
{query.length > 0
? 'Нет контактов по такому запросу'
: 'Контакты с ключами шифрования отсутствуют'}
? 'No contacts match this search'
: 'No contacts with encryption keys yet'}
</Text>
</View>
}
@@ -227,8 +227,8 @@ export function ShareSheet({ visible, post, onClose }: ShareSheetProps) {
fontSize: 14,
}}>
{picked.size === 0
? 'Выберите контакты'
: `Отправить (${picked.size})`}
? 'Select contacts'
: `Send (${picked.size})`}
</Text>
)}
</Pressable>
@@ -298,10 +298,5 @@ function shortAddr(a: string, n = 6): string {
}
function plural(n: number): string {
const mod100 = n % 100;
const mod10 = n % 10;
if (mod100 >= 11 && mod100 <= 19) return 'ов';
if (mod10 === 1) return '';
if (mod10 >= 2 && mod10 <= 4) return 'а';
return 'ов';
return n === 1 ? 'chat' : 'chats';
}