mirror of
https://github.com/stablyai/orca.git
synced 2026-11-01 17:47:40 +00:00
* feat(mobile): add UI localization infrastructure Mobile follows the phone's language (or an in-app choice under Settings > Appearance) across the same 11 languages as desktop, switching live like the theme does. - i18next with desktop's translate(key, fallback, options) call shape; catalogs in mobile/src/i18n/locales load lazily, English fallbacks stay inline - Hermes lacks Intl.PluralRules: load the FormatJS polyfill with the 11 languages' rules - OTA pages get the shell's language through an optional bridge init field - iOS permission prompts localized; iOS and Android 13+ per-app language pickers - verify:mobile-localization and a coverage ratchet run in lint, check:changed and CI * fix(mobile): mount pages after the newest language request; tighten localization gates - Wait for the latest page language activation, not a superseded one - Keep literal fallbacks when a key also has a dynamic one - Count headerTitle as visible copy; select the mobile check when the runtime catalog generator changes * feat(mobile): repaint themed components on language changes Components that read the theme already subscribe for repaint; a language switch repaints them too, so labels built by helpers during render follow it. RPC recordings load the real i18next and JSON catalogs. * fix(mobile): scope the translate() gate to render bodies and memos; prune stale keys on sync Handlers and effects may call translate() when they run. sync:mobile-localization now removes keys no code references from every catalog. * fix(mobile): use node: imports in the locale config plugin; pass uiLocale in bridge hook test * chore(mobile): refresh the localization coverage baseline * fix(mobile): follow render callbacks in the translate() gate; keep used plural siblings on prune Also let anonymous default-exported screens count as components, flag any plural family a locale started, and mark JSON modules as ES modules in the recording loader. * fix(mobile): treat async and named local callbacks as handlers in the translate() gate * chore(mobile): refresh the localization coverage baseline * chore(mobile): refresh the localization coverage baseline --------- Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
32 lines
1.2 KiB
JavaScript
32 lines
1.2 KiB
JavaScript
const fs = require('node:fs')
|
|
const path = require('node:path')
|
|
const { withAndroidManifest, withDangerousMod, AndroidConfig } = require('expo/config-plugins')
|
|
|
|
// Declares the Android 13+ per-app language list. expo-localization's own Android option also
|
|
// strips every other language from dependency resources, so only its iOS half is used.
|
|
module.exports = function withAndroidLocaleConfig(config, { locales }) {
|
|
config = withDangerousMod(config, [
|
|
'android',
|
|
(cfg) => {
|
|
const folder = path.join(cfg.modRequest.platformProjectRoot, 'app/src/main/res/xml')
|
|
fs.mkdirSync(folder, { recursive: true })
|
|
fs.writeFileSync(
|
|
path.join(folder, 'locales_config.xml'),
|
|
[
|
|
'<?xml version="1.0" encoding="utf-8"?>',
|
|
'<locale-config xmlns:android="http://schemas.android.com/apk/res/android">',
|
|
...locales.map((locale) => ` <locale android:name="${locale}"/>`),
|
|
'</locale-config>',
|
|
''
|
|
].join('\n')
|
|
)
|
|
return cfg
|
|
}
|
|
])
|
|
return withAndroidManifest(config, (cfg) => {
|
|
const application = AndroidConfig.Manifest.getMainApplicationOrThrow(cfg.modResults)
|
|
application.$['android:localeConfig'] = '@xml/locales_config'
|
|
return cfg
|
|
})
|
|
}
|