feat(i18n): add i18n infrastructure + Simplified Chinese, localize Settings screen (refs #68) (#97)

- Add expo-localization, i18next, react-i18next (versions aligned with
  Expo 54 / RN 0.81)
- src/lib/i18n/locale-resolve.ts: pure locale-resolution helpers
  (system tag -> supported catalog, with en fallback), unit-tested via
  node --test with no RN imports
- src/lib/i18n/config.ts: i18next init wired to expo-localization
  device detection, en.json + zh-Hans.json catalogs
- Persist a locale preference (system | en | zh-Hans) in the settings
  zustand store, applied immediately via i18next.changeLanguage
- Wire I18nextProvider in app/_layout.tsx
- Localize the Settings screen (~28 strings) as the reference pattern
  for extracting user-facing strings, with a language picker row and
  reviewed Simplified Chinese translations

Other screens (session/[id], connection/*, index, chat components)
are deferred follow-up — issue #68 stays open for that work.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Den
2026-07-17 02:47:18 -07:00
committed by GitHub
parent f4e1a9a757
commit baf73058fd
11 changed files with 441 additions and 48 deletions

69
src/lib/i18n/en.json Normal file
View File

@@ -0,0 +1,69 @@
{
"common": {
"cancel": "Cancel"
},
"settings": {
"sections": {
"security": "Security",
"notifications": "Notifications",
"privacy": "Privacy",
"about": "About"
},
"security": {
"biometricOpen": {
"label": "Require Biometric to Open",
"descriptionEnabled": "Use Face ID or Touch ID to unlock the app",
"descriptionUnavailable": "Biometric authentication not available"
},
"biometricSend": {
"label": "Require Biometric to Send",
"description": "Authenticate before sending messages"
},
"lockNow": {
"label": "Lock App Now",
"description": "Require authentication to reopen"
}
},
"notifications": {
"disabledNotice": "Notifications are disabled at the system level. Enable them in Settings to receive alerts."
},
"privacy": {
"crashReporting": {
"label": "Crash Reporting",
"description": "Share anonymous crash reports via Sentry to help improve OpenCode. No code or prompts are included."
},
"privacyPolicy": {
"label": "Privacy Policy",
"description": "What data we collect and how"
}
},
"about": {
"version": "Version",
"github": {
"label": "GitHub",
"description": "View source code"
},
"docs": {
"label": "Documentation",
"description": "Learn how to use OpenCode"
}
},
"language": {
"label": "Language",
"title": "Choose Language",
"system": "System Default",
"en": "English",
"zhHans": "Simplified Chinese"
},
"footer": {
"appName": "OpenCode Mobile",
"tagline": "Connect to your AI coding assistant from anywhere"
},
"alerts": {
"privacyNotSavedTitle": "Privacy Setting Not Saved",
"privacyNotSavedMessage": "Crash reporting is off for this session, but your choice could not be saved. Please try again.",
"notificationsDisabledTitle": "Notifications Disabled",
"notificationsDisabledMessage": "Enable notifications for OpenCode in your device settings to receive alerts."
}
}
}