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:
@@ -27,9 +27,9 @@ import { SearchBar } from '@/components/SearchBar';
|
||||
|
||||
const MIN_CONTACT_FEE = 5000;
|
||||
const FEE_TIERS = [
|
||||
{ value: 5_000, label: 'Базовая' },
|
||||
{ value: 10_000, label: 'Стандарт' },
|
||||
{ value: 50_000, label: 'Приоритет' },
|
||||
{ value: 5_000, label: 'Min' },
|
||||
{ value: 10_000, label: 'Standard' },
|
||||
{ value: 50_000, label: 'Priority' },
|
||||
];
|
||||
|
||||
interface Resolved {
|
||||
@@ -61,7 +61,7 @@ export default function NewContactScreen() {
|
||||
if (q.startsWith('@') || (!q.match(/^[0-9a-f]{64}$/i) && !q.startsWith('DC'))) {
|
||||
const name = q.replace('@', '');
|
||||
const addr = await resolveUsername(settings.contractId, name);
|
||||
if (!addr) { setError(`@${name} не зарегистрирован в этой сети`); return; }
|
||||
if (!addr) { setError(`@${name} is not registered on this chain`); return; }
|
||||
address = addr;
|
||||
}
|
||||
const identity = await getIdentity(address);
|
||||
@@ -71,7 +71,7 @@ export default function NewContactScreen() {
|
||||
x25519: identity?.x25519_pub || undefined,
|
||||
});
|
||||
} catch (e: any) {
|
||||
setError(e?.message ?? 'Не удалось найти пользователя');
|
||||
setError(e?.message ?? 'Lookup failed');
|
||||
} finally {
|
||||
setSearching(false);
|
||||
}
|
||||
@@ -80,7 +80,7 @@ export default function NewContactScreen() {
|
||||
async function sendRequest() {
|
||||
if (!resolved || !keyFile) return;
|
||||
if (balance < fee + 1000) {
|
||||
Alert.alert('Недостаточно средств', `Нужно ${formatAmount(fee + 1000)} (плата + сетевая комиссия).`);
|
||||
Alert.alert('Insufficient balance', `Need ${formatAmount(fee + 1000)} (request fee + network).`);
|
||||
return;
|
||||
}
|
||||
setSending(true); setError(null);
|
||||
@@ -94,8 +94,8 @@ export default function NewContactScreen() {
|
||||
});
|
||||
await submitTx(tx);
|
||||
Alert.alert(
|
||||
'Запрос отправлен',
|
||||
`Запрос на общение отправлен ${resolved.nickname ? '@' + resolved.nickname : shortAddr(resolved.address)}.`,
|
||||
'Request sent',
|
||||
`A contact request has been sent to ${resolved.nickname ? '@' + resolved.nickname : shortAddr(resolved.address)}.`,
|
||||
[{ text: 'OK', onPress: () => router.back() }],
|
||||
);
|
||||
} catch (e: any) {
|
||||
@@ -112,7 +112,7 @@ export default function NewContactScreen() {
|
||||
return (
|
||||
<View style={{ flex: 1, backgroundColor: '#000000', paddingTop: insets.top }}>
|
||||
<Header
|
||||
title="Поиск"
|
||||
title="Search"
|
||||
divider={false}
|
||||
left={<IconButton icon="chevron-back" size={36} onPress={() => router.back()} />}
|
||||
/>
|
||||
@@ -124,7 +124,7 @@ export default function NewContactScreen() {
|
||||
<SearchBar
|
||||
value={query}
|
||||
onChangeText={setQuery}
|
||||
placeholder="@alice, hex pubkey или DC-адрес"
|
||||
placeholder="@alice, hex pubkey or DC address"
|
||||
onSubmitEditing={search}
|
||||
autoFocus
|
||||
onClear={() => { setResolved(null); setError(null); }}
|
||||
@@ -143,7 +143,7 @@ export default function NewContactScreen() {
|
||||
{searching ? (
|
||||
<ActivityIndicator color="#ffffff" size="small" />
|
||||
) : (
|
||||
<Text style={{ color: '#ffffff', fontWeight: '700', fontSize: 14 }}>Найти</Text>
|
||||
<Text style={{ color: '#ffffff', fontWeight: '700', fontSize: 14 }}>Search</Text>
|
||||
)}
|
||||
</Pressable>
|
||||
)}
|
||||
@@ -163,11 +163,11 @@ export default function NewContactScreen() {
|
||||
<Ionicons name="person-add-outline" size={24} color="#6a6a6a" />
|
||||
</View>
|
||||
<Text style={{ color: '#ffffff', fontSize: 15, fontWeight: '700', marginBottom: 6 }}>
|
||||
Найдите собеседника
|
||||
Find someone to message
|
||||
</Text>
|
||||
<Text style={{ color: '#8b8b8b', fontSize: 13, textAlign: 'center', lineHeight: 19 }}>
|
||||
Введите <Text style={{ color: '#ffffff', fontWeight: '600' }}>@username</Text>,
|
||||
если человек зарегистрировал ник, либо полный hex pubkey или <Text style={{ color: '#ffffff', fontWeight: '600' }}>DC…</Text> адрес.
|
||||
Enter an <Text style={{ color: '#ffffff', fontWeight: '600' }}>@username</Text> if
|
||||
the person registered one, or paste a full hex pubkey or <Text style={{ color: '#ffffff', fontWeight: '600' }}>DC…</Text> address.
|
||||
</Text>
|
||||
</View>
|
||||
)}
|
||||
@@ -218,7 +218,7 @@ export default function NewContactScreen() {
|
||||
color: resolved.x25519 ? '#3ba55d' : '#f0b35a',
|
||||
fontSize: 11, fontWeight: '500',
|
||||
}}>
|
||||
{resolved.x25519 ? 'E2E готов' : 'Ключ ещё не опубликован'}
|
||||
{resolved.x25519 ? 'E2E ready' : 'Key not published yet'}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
@@ -227,12 +227,12 @@ export default function NewContactScreen() {
|
||||
|
||||
{/* Intro */}
|
||||
<Text style={{ color: '#8b8b8b', fontSize: 12, marginTop: 18, marginBottom: 6 }}>
|
||||
Сообщение (опционально, видно в открытом виде на chain)
|
||||
Intro (optional, plaintext on-chain)
|
||||
</Text>
|
||||
<TextInput
|
||||
value={intro}
|
||||
onChangeText={setIntro}
|
||||
placeholder="Привет! Это Влад со встречи в среду"
|
||||
placeholder="Hey, it's Jordan from the conference"
|
||||
placeholderTextColor="#5a5a5a"
|
||||
multiline
|
||||
maxLength={140}
|
||||
@@ -250,7 +250,7 @@ export default function NewContactScreen() {
|
||||
|
||||
{/* Fee tier */}
|
||||
<Text style={{ color: '#8b8b8b', fontSize: 12, marginTop: 14, marginBottom: 6 }}>
|
||||
Плата за запрос (уходит получателю, anti-spam)
|
||||
Anti-spam fee (goes to the recipient)
|
||||
</Text>
|
||||
{/* Fee-tier pills.
|
||||
Layout (background, border, padding) lives on a static
|
||||
@@ -314,7 +314,7 @@ export default function NewContactScreen() {
|
||||
<ActivityIndicator color="#ffffff" size="small" />
|
||||
) : (
|
||||
<Text style={{ color: '#ffffff', fontWeight: '700', fontSize: 14 }}>
|
||||
Отправить запрос · {formatAmount(fee + 1000)}
|
||||
Send request · {formatAmount(fee + 1000)}
|
||||
</Text>
|
||||
)}
|
||||
</Pressable>
|
||||
|
||||
Reference in New Issue
Block a user