@djangocfg/i18n 2.1.584 → 2.1.586
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -0
- package/dist/index.d.mts +1 -12
- package/dist/index.mjs +0 -30
- package/dist/index.mjs.map +1 -1
- package/package.json +11 -2
- package/src/copy/createCopy.ts +41 -0
- package/src/copy/format.ts +50 -0
- package/src/copy/index.ts +3 -0
- package/src/copy/locales.ts +46 -0
- package/src/copy/testing.ts +79 -0
- package/src/locales/ar.ts +0 -10
- package/src/locales/da.ts +0 -10
- package/src/locales/de.ts +0 -10
- package/src/locales/en.ts +0 -10
- package/src/locales/es.ts +0 -10
- package/src/locales/fr.ts +0 -10
- package/src/locales/it.ts +0 -10
- package/src/locales/ja.ts +0 -10
- package/src/locales/ko.ts +0 -10
- package/src/locales/nl.ts +0 -10
- package/src/locales/no.ts +0 -10
- package/src/locales/pl.ts +0 -10
- package/src/locales/pt-BR.ts +0 -10
- package/src/locales/ru.ts +0 -10
- package/src/locales/sv.ts +0 -10
- package/src/locales/tr.ts +0 -10
- package/src/locales/zh.ts +0 -10
- package/src/types.ts +0 -12
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@djangocfg/i18n",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.586",
|
|
4
4
|
"description": "Lightweight i18n library for @djangocfg packages with built-in translations for English, Russian, and Korean",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"i18n",
|
|
@@ -41,6 +41,14 @@
|
|
|
41
41
|
"import": "./src/locales/index.ts"
|
|
42
42
|
},
|
|
43
43
|
"./locales/*": "./src/locales/*.ts",
|
|
44
|
+
"./copy": {
|
|
45
|
+
"types": "./src/copy/index.ts",
|
|
46
|
+
"import": "./src/copy/index.ts"
|
|
47
|
+
},
|
|
48
|
+
"./copy/testing": {
|
|
49
|
+
"types": "./src/copy/testing.ts",
|
|
50
|
+
"import": "./src/copy/testing.ts"
|
|
51
|
+
},
|
|
44
52
|
"./utils": {
|
|
45
53
|
"types": "./src/utils/index.ts",
|
|
46
54
|
"import": "./src/utils/index.ts"
|
|
@@ -53,6 +61,7 @@
|
|
|
53
61
|
"files": [
|
|
54
62
|
"dist",
|
|
55
63
|
"src",
|
|
64
|
+
"@docs",
|
|
56
65
|
"README.md",
|
|
57
66
|
"LICENSE"
|
|
58
67
|
],
|
|
@@ -75,7 +84,7 @@
|
|
|
75
84
|
"jiti": "^2.7.0"
|
|
76
85
|
},
|
|
77
86
|
"devDependencies": {
|
|
78
|
-
"@djangocfg/typescript-config": "^2.1.
|
|
87
|
+
"@djangocfg/typescript-config": "^2.1.586",
|
|
79
88
|
"@types/node": "^25.9.5",
|
|
80
89
|
"@types/react": "19.2.15",
|
|
81
90
|
"eslint": "^9.39.5",
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { useMemo } from 'react'
|
|
2
|
+
|
|
3
|
+
import { useLocaleOptional } from '../context'
|
|
4
|
+
import { resolveLocale, type Dictionaries, type Locale } from './locales'
|
|
5
|
+
|
|
6
|
+
export interface CopyKit<T> {
|
|
7
|
+
/** Every bundled dictionary, for tests and tooling. */
|
|
8
|
+
readonly dictionaries: Dictionaries<T>
|
|
9
|
+
/** The dictionary for a language tag; English when it is not bundled. */
|
|
10
|
+
resolve(tag: string | null | undefined): T
|
|
11
|
+
/**
|
|
12
|
+
* The dictionary for the active language: the `locale` prop when the host
|
|
13
|
+
* passes one, else the `@djangocfg/i18n` provider, else English. With no
|
|
14
|
+
* provider (a story, a test) it renders without one.
|
|
15
|
+
*/
|
|
16
|
+
useCopy(locale?: string): T
|
|
17
|
+
/** The bundled locale `useCopy` resolved to; feed it to `plural()`. */
|
|
18
|
+
useLocale(locale?: string): Locale
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Wire a package's own dictionaries to the shared locale contract.
|
|
23
|
+
*
|
|
24
|
+
* The package keeps its strings and its `XCopy` schema; this supplies the one
|
|
25
|
+
* resolver and the one hook, so locale handling is identical everywhere.
|
|
26
|
+
*/
|
|
27
|
+
export function createCopy<T>(dictionaries: Dictionaries<T>): CopyKit<T> {
|
|
28
|
+
const resolve = (tag: string | null | undefined): T => dictionaries[resolveLocale(tag)]
|
|
29
|
+
|
|
30
|
+
function useLocale(locale?: string): Locale {
|
|
31
|
+
const fromProvider = useLocaleOptional()
|
|
32
|
+
return resolveLocale(locale ?? fromProvider)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function useCopy(locale?: string): T {
|
|
36
|
+
const resolved = useLocale(locale)
|
|
37
|
+
return useMemo(() => dictionaries[resolved], [resolved])
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return { dictionaries, resolve, useCopy, useLocale }
|
|
41
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/** The plural categories `Intl.PluralRules` can report; only `other` is required. */
|
|
2
|
+
export interface PluralCopy {
|
|
3
|
+
readonly zero?: string
|
|
4
|
+
readonly one?: string
|
|
5
|
+
readonly two?: string
|
|
6
|
+
readonly few?: string
|
|
7
|
+
readonly many?: string
|
|
8
|
+
readonly other: string
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export type FillValues = Readonly<Record<string, string | number>>
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Fill `{{name}}` placeholders. The placeholder belongs to the dictionary, so a
|
|
15
|
+
* translator can move it; a template literal at the call site could not.
|
|
16
|
+
*/
|
|
17
|
+
export function fill(template: string, values: FillValues): string {
|
|
18
|
+
return template.replace(/\{\{(\w+)\}\}/g, (whole, key: string) => {
|
|
19
|
+
const value = values[key]
|
|
20
|
+
return value === undefined ? whole : String(value)
|
|
21
|
+
})
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Building a PluralRules costs a locale-data lookup and plurals render often.
|
|
25
|
+
const rules = new Map<string, Intl.PluralRules>()
|
|
26
|
+
|
|
27
|
+
function rulesFor(language: string): Intl.PluralRules {
|
|
28
|
+
const cached = rules.get(language)
|
|
29
|
+
if (cached) return cached
|
|
30
|
+
let made: Intl.PluralRules
|
|
31
|
+
try {
|
|
32
|
+
made = new Intl.PluralRules(language)
|
|
33
|
+
} catch {
|
|
34
|
+
// An invalid tag throws; a wrong plural beats a crashed render.
|
|
35
|
+
made = new Intl.PluralRules('en')
|
|
36
|
+
}
|
|
37
|
+
rules.set(language, made)
|
|
38
|
+
return made
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** Pick the plural form for `count` and fill `{{count}}`; `other` is the fallback. */
|
|
42
|
+
export function plural(
|
|
43
|
+
copy: PluralCopy,
|
|
44
|
+
count: number,
|
|
45
|
+
language: string,
|
|
46
|
+
values: FillValues = {},
|
|
47
|
+
): string {
|
|
48
|
+
const template = copy[rulesFor(language).select(count)] ?? copy.other
|
|
49
|
+
return fill(template, { ...values, count })
|
|
50
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The locales a self-contained package ships a dictionary for.
|
|
3
|
+
*
|
|
4
|
+
* One list for every widget: a package that forgets a language fails `tsc`
|
|
5
|
+
* (see `Dictionaries`) instead of quietly rendering English for it.
|
|
6
|
+
*/
|
|
7
|
+
export const LOCALES = [
|
|
8
|
+
'en', 'ru', 'ko', 'ja', 'de', 'fr', 'zh', 'it', 'es',
|
|
9
|
+
'nl', 'ar', 'tr', 'pl', 'sv', 'no', 'da', 'pt-BR',
|
|
10
|
+
] as const
|
|
11
|
+
|
|
12
|
+
export type Locale = (typeof LOCALES)[number]
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* A complete set of dictionaries. `Record` over the closed `Locale` union, so
|
|
16
|
+
* a missing language is a type error at the registry, not a runtime miss.
|
|
17
|
+
*/
|
|
18
|
+
export type Dictionaries<T> = Readonly<Record<Locale, T>>
|
|
19
|
+
|
|
20
|
+
/** Language tags hosts report that name one of our locales under another code. */
|
|
21
|
+
const ALIASES: Readonly<Record<string, Locale>> = {
|
|
22
|
+
nb: 'no',
|
|
23
|
+
nn: 'no',
|
|
24
|
+
pt: 'pt-BR',
|
|
25
|
+
'pt-pt': 'pt-BR',
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const BY_LOWER = new Map<string, Locale>(LOCALES.map((l) => [l.toLowerCase(), l]))
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Map whatever language tag the host reports to a bundled locale.
|
|
32
|
+
*
|
|
33
|
+
* Exact match, then the base language (`zh-CN` → `zh`), then an alias
|
|
34
|
+
* (`nb` → `no`), then English. One resolver for every package, so two widgets
|
|
35
|
+
* on one page never disagree about what `pt` means.
|
|
36
|
+
*/
|
|
37
|
+
export function resolveLocale(tag: string | null | undefined): Locale {
|
|
38
|
+
if (!tag) return 'en'
|
|
39
|
+
const lower = tag.replace('_', '-').toLowerCase()
|
|
40
|
+
const exact = BY_LOWER.get(lower)
|
|
41
|
+
if (exact) return exact
|
|
42
|
+
const alias = ALIASES[lower]
|
|
43
|
+
if (alias) return alias
|
|
44
|
+
const base = lower.split('-')[0] ?? ''
|
|
45
|
+
return BY_LOWER.get(base) ?? ALIASES[base] ?? 'en'
|
|
46
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { readdirSync } from 'node:fs'
|
|
2
|
+
|
|
3
|
+
import { LOCALES } from './locales'
|
|
4
|
+
|
|
5
|
+
type Tree = { readonly [key: string]: string | Tree }
|
|
6
|
+
|
|
7
|
+
function leaves(tree: Tree, prefix = ''): Map<string, string> {
|
|
8
|
+
const out = new Map<string, string>()
|
|
9
|
+
for (const [key, value] of Object.entries(tree)) {
|
|
10
|
+
const path = prefix ? `${prefix}.${key}` : key
|
|
11
|
+
if (typeof value === 'string') out.set(path, value)
|
|
12
|
+
else for (const [p, v] of leaves(value, path)) out.set(p, v)
|
|
13
|
+
}
|
|
14
|
+
return out
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const placeholders = (s: string): string =>
|
|
18
|
+
[...s.matchAll(/\{{1,2}(\w+)\}{1,2}/g)].map((m) => m[1]).sort().join(',')
|
|
19
|
+
|
|
20
|
+
// A language has the plural forms it has (`ko` has no `one`, `ru` adds `few`
|
|
21
|
+
// and `many`), so only `other` is a fixed key under a `PluralCopy`.
|
|
22
|
+
const OPTIONAL_FORMS = new Set(['zero', 'one', 'two', 'few', 'many'])
|
|
23
|
+
const isOptionalForm = (path: string): boolean => OPTIONAL_FORMS.has(path.split('.').pop() ?? '')
|
|
24
|
+
|
|
25
|
+
const norm = (s: string): string => s.replace('-', '').toLowerCase()
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* What `tsc` cannot check about a package's dictionaries; returns problems,
|
|
29
|
+
* empty when clean:
|
|
30
|
+
*
|
|
31
|
+
* - the registry covers every locale in `LOCALES`;
|
|
32
|
+
* - every file in `localesDir` is registered (written, never wired in);
|
|
33
|
+
* - every dictionary has the same keys as English (plural forms other than
|
|
34
|
+
* `other` may differ per language);
|
|
35
|
+
* - every string is non-blank and keeps the `{{placeholders}}` English has.
|
|
36
|
+
*
|
|
37
|
+
* `dictionaries` is typed loosely so any `XCopy` can be passed without a cast.
|
|
38
|
+
*/
|
|
39
|
+
export function checkDictionaries(
|
|
40
|
+
dictionaries: Readonly<Record<string, object>>,
|
|
41
|
+
localesDir: string,
|
|
42
|
+
): string[] {
|
|
43
|
+
const problems: string[] = []
|
|
44
|
+
const registered = Object.keys(dictionaries)
|
|
45
|
+
|
|
46
|
+
for (const locale of LOCALES) {
|
|
47
|
+
if (!registered.includes(locale)) problems.push(`locale not registered: ${locale}`)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const onDisk = readdirSync(localesDir)
|
|
51
|
+
.filter((n) => n.endsWith('.ts'))
|
|
52
|
+
.map((n) => n.replace(/\.ts$/, ''))
|
|
53
|
+
if (onDisk.length === 0) problems.push(`no dictionary files in ${localesDir}`)
|
|
54
|
+
for (const file of onDisk) {
|
|
55
|
+
if (!registered.some((k) => norm(k) === norm(file))) {
|
|
56
|
+
problems.push(`file not registered: ${file}`)
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const en = dictionaries.en
|
|
61
|
+
if (!en) return [...problems, 'no English dictionary']
|
|
62
|
+
const reference = leaves(en as Tree)
|
|
63
|
+
for (const [locale, dict] of Object.entries(dictionaries)) {
|
|
64
|
+
const own = leaves(dict as Tree)
|
|
65
|
+
for (const [path, text] of reference) {
|
|
66
|
+
const got = own.get(path)
|
|
67
|
+
if (got === undefined) {
|
|
68
|
+
if (!isOptionalForm(path)) problems.push(`${locale}: missing ${path}`)
|
|
69
|
+
} else if (got.trim() === '') problems.push(`${locale}: blank ${path}`)
|
|
70
|
+
else if (placeholders(got) !== placeholders(text)) {
|
|
71
|
+
problems.push(`${locale}: placeholders differ at ${path}`)
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
for (const path of own.keys()) {
|
|
75
|
+
if (!reference.has(path) && !isOptionalForm(path)) problems.push(`${locale}: extra ${path}`)
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return problems
|
|
79
|
+
}
|
package/src/locales/ar.ts
CHANGED
|
@@ -311,16 +311,6 @@ export const ar: I18nTranslations = {
|
|
|
311
311
|
anyCodeWorks: "وضع التطوير: أي رمز يعمل",
|
|
312
312
|
},
|
|
313
313
|
},
|
|
314
|
-
chat: {
|
|
315
|
-
aiAssistant: "مساعد الذكاء الاصطناعي",
|
|
316
|
-
defaultTitle: "محادثة الذكاء الاصطناعي",
|
|
317
|
-
newChat: "محادثة جديدة",
|
|
318
|
-
closeChat: "إغلاق المحادثة",
|
|
319
|
-
switchToFloating: "التبديل للوضع العائم",
|
|
320
|
-
switchToSidebar: "التبديل لوضع الشريط الجانبي",
|
|
321
|
-
dragToResize: "اسحب لتغيير الحجم",
|
|
322
|
-
howCanIHelp: "كيف يمكنني مساعدتك؟",
|
|
323
|
-
},
|
|
324
314
|
pwa: {
|
|
325
315
|
addToHomeScreen: "إضافة للشاشة الرئيسية",
|
|
326
316
|
installApp: "تثبيت التطبيق",
|
package/src/locales/da.ts
CHANGED
|
@@ -311,16 +311,6 @@ export const da: I18nTranslations = {
|
|
|
311
311
|
anyCodeWorks: "Dev-tilstand: Enhver kode virker",
|
|
312
312
|
},
|
|
313
313
|
},
|
|
314
|
-
chat: {
|
|
315
|
-
aiAssistant: "AI-assistent",
|
|
316
|
-
defaultTitle: "AI-chat",
|
|
317
|
-
newChat: "Ny chat",
|
|
318
|
-
closeChat: "Luk chat",
|
|
319
|
-
switchToFloating: "Skift til flydende tilstand",
|
|
320
|
-
switchToSidebar: "Skift til sidepaneltilstand",
|
|
321
|
-
dragToResize: "Træk for at ændre størrelse",
|
|
322
|
-
howCanIHelp: "Hvordan kan jeg hjælpe dig?",
|
|
323
|
-
},
|
|
324
314
|
pwa: {
|
|
325
315
|
addToHomeScreen: "Tilføj til startskærm",
|
|
326
316
|
installApp: "Installer app",
|
package/src/locales/de.ts
CHANGED
|
@@ -311,16 +311,6 @@ export const de: I18nTranslations = {
|
|
|
311
311
|
anyCodeWorks: "Entwicklermodus: Jeder Code funktioniert",
|
|
312
312
|
},
|
|
313
313
|
},
|
|
314
|
-
chat: {
|
|
315
|
-
aiAssistant: "KI-Assistent",
|
|
316
|
-
defaultTitle: "KI-Chat",
|
|
317
|
-
newChat: "Neuer Chat",
|
|
318
|
-
closeChat: "Chat schließen",
|
|
319
|
-
switchToFloating: "Zu schwebendem Modus wechseln",
|
|
320
|
-
switchToSidebar: "Zu Seitenleistenmodus wechseln",
|
|
321
|
-
dragToResize: "Ziehen zum Ändern der Größe",
|
|
322
|
-
howCanIHelp: "Wie kann ich helfen?",
|
|
323
|
-
},
|
|
324
314
|
pwa: {
|
|
325
315
|
addToHomeScreen: "Zum Startbildschirm hinzufügen",
|
|
326
316
|
installApp: "App installieren",
|
package/src/locales/en.ts
CHANGED
|
@@ -311,16 +311,6 @@ export const en: I18nTranslations = {
|
|
|
311
311
|
anyCodeWorks: "Dev Mode: Any code works",
|
|
312
312
|
},
|
|
313
313
|
},
|
|
314
|
-
chat: {
|
|
315
|
-
aiAssistant: "AI Assistant",
|
|
316
|
-
defaultTitle: "AI Chat",
|
|
317
|
-
newChat: "New chat",
|
|
318
|
-
closeChat: "Close chat",
|
|
319
|
-
switchToFloating: "Switch to floating mode",
|
|
320
|
-
switchToSidebar: "Switch to sidebar mode",
|
|
321
|
-
dragToResize: "Drag to resize",
|
|
322
|
-
howCanIHelp: "How can I help?",
|
|
323
|
-
},
|
|
324
314
|
pwa: {
|
|
325
315
|
addToHomeScreen: "Add to Home Screen",
|
|
326
316
|
installApp: "Install App",
|
package/src/locales/es.ts
CHANGED
|
@@ -311,16 +311,6 @@ export const es: I18nTranslations = {
|
|
|
311
311
|
anyCodeWorks: "Modo Dev: Cualquier código funciona",
|
|
312
312
|
},
|
|
313
313
|
},
|
|
314
|
-
chat: {
|
|
315
|
-
aiAssistant: "Asistente de IA",
|
|
316
|
-
defaultTitle: "Chat de IA",
|
|
317
|
-
newChat: "Nueva conversación",
|
|
318
|
-
closeChat: "Cerrar chat",
|
|
319
|
-
switchToFloating: "Cambiar a modo flotante",
|
|
320
|
-
switchToSidebar: "Cambiar a modo barra lateral",
|
|
321
|
-
dragToResize: "Arrastra para redimensionar",
|
|
322
|
-
howCanIHelp: "¿Cómo puedo ayudarte?",
|
|
323
|
-
},
|
|
324
314
|
pwa: {
|
|
325
315
|
addToHomeScreen: "Agregar a pantalla de inicio",
|
|
326
316
|
installApp: "Instalar aplicación",
|
package/src/locales/fr.ts
CHANGED
|
@@ -311,16 +311,6 @@ export const fr: I18nTranslations = {
|
|
|
311
311
|
anyCodeWorks: "Mode Dev: N'importe quel code fonctionne",
|
|
312
312
|
},
|
|
313
313
|
},
|
|
314
|
-
chat: {
|
|
315
|
-
aiAssistant: "Assistant IA",
|
|
316
|
-
defaultTitle: "Chat IA",
|
|
317
|
-
newChat: "Nouvelle conversation",
|
|
318
|
-
closeChat: "Fermer le chat",
|
|
319
|
-
switchToFloating: "Passer en mode flottant",
|
|
320
|
-
switchToSidebar: "Passer en mode barre latérale",
|
|
321
|
-
dragToResize: "Glisser pour redimensionner",
|
|
322
|
-
howCanIHelp: "Comment puis-je vous aider?",
|
|
323
|
-
},
|
|
324
314
|
pwa: {
|
|
325
315
|
addToHomeScreen: "Ajouter à l'écran d'accueil",
|
|
326
316
|
installApp: "Installer l'application",
|
package/src/locales/it.ts
CHANGED
|
@@ -311,16 +311,6 @@ export const it: I18nTranslations = {
|
|
|
311
311
|
anyCodeWorks: "Modalità Dev: Qualsiasi codice funziona",
|
|
312
312
|
},
|
|
313
313
|
},
|
|
314
|
-
chat: {
|
|
315
|
-
aiAssistant: "Assistente IA",
|
|
316
|
-
defaultTitle: "Chat IA",
|
|
317
|
-
newChat: "Nuova chat",
|
|
318
|
-
closeChat: "Chiudi chat",
|
|
319
|
-
switchToFloating: "Passa a modalità flottante",
|
|
320
|
-
switchToSidebar: "Passa a modalità barra laterale",
|
|
321
|
-
dragToResize: "Trascina per ridimensionare",
|
|
322
|
-
howCanIHelp: "Come posso aiutarti?",
|
|
323
|
-
},
|
|
324
314
|
pwa: {
|
|
325
315
|
addToHomeScreen: "Aggiungi alla schermata Home",
|
|
326
316
|
installApp: "Installa l'app",
|
package/src/locales/ja.ts
CHANGED
|
@@ -311,16 +311,6 @@ export const ja: I18nTranslations = {
|
|
|
311
311
|
anyCodeWorks: "開発モード: 任意のコードが有効",
|
|
312
312
|
},
|
|
313
313
|
},
|
|
314
|
-
chat: {
|
|
315
|
-
aiAssistant: "AIアシスタント",
|
|
316
|
-
defaultTitle: "AIチャット",
|
|
317
|
-
newChat: "新しいチャット",
|
|
318
|
-
closeChat: "チャットを閉じる",
|
|
319
|
-
switchToFloating: "フローティングモードに切り替え",
|
|
320
|
-
switchToSidebar: "サイドバーモードに切り替え",
|
|
321
|
-
dragToResize: "ドラッグしてサイズ変更",
|
|
322
|
-
howCanIHelp: "お手伝いできることはありますか?",
|
|
323
|
-
},
|
|
324
314
|
pwa: {
|
|
325
315
|
addToHomeScreen: "ホーム画面に追加",
|
|
326
316
|
installApp: "アプリをインストール",
|
package/src/locales/ko.ts
CHANGED
|
@@ -311,16 +311,6 @@ export const ko: I18nTranslations = {
|
|
|
311
311
|
anyCodeWorks: "개발 모드: 아무 코드나 사용 가능",
|
|
312
312
|
},
|
|
313
313
|
},
|
|
314
|
-
chat: {
|
|
315
|
-
aiAssistant: "AI 어시스턴트",
|
|
316
|
-
defaultTitle: "AI 채팅",
|
|
317
|
-
newChat: "새 채팅",
|
|
318
|
-
closeChat: "채팅 닫기",
|
|
319
|
-
switchToFloating: "플로팅 모드로 전환",
|
|
320
|
-
switchToSidebar: "사이드바 모드로 전환",
|
|
321
|
-
dragToResize: "드래그하여 크기 조절",
|
|
322
|
-
howCanIHelp: "무엇을 도와드릴까요?",
|
|
323
|
-
},
|
|
324
314
|
pwa: {
|
|
325
315
|
addToHomeScreen: "홈 화면에 추가",
|
|
326
316
|
installApp: "앱 설치",
|
package/src/locales/nl.ts
CHANGED
|
@@ -311,16 +311,6 @@ export const nl: I18nTranslations = {
|
|
|
311
311
|
anyCodeWorks: "Dev Mode: Elke code werkt",
|
|
312
312
|
},
|
|
313
313
|
},
|
|
314
|
-
chat: {
|
|
315
|
-
aiAssistant: "AI-assistent",
|
|
316
|
-
defaultTitle: "AI Chat",
|
|
317
|
-
newChat: "Nieuwe chat",
|
|
318
|
-
closeChat: "Chat sluiten",
|
|
319
|
-
switchToFloating: "Naar zwevende modus",
|
|
320
|
-
switchToSidebar: "Naar zijbalkmodus",
|
|
321
|
-
dragToResize: "Sleep om te vergroten/verkleinen",
|
|
322
|
-
howCanIHelp: "Hoe kan ik helpen?",
|
|
323
|
-
},
|
|
324
314
|
pwa: {
|
|
325
315
|
addToHomeScreen: "Toevoegen aan startscherm",
|
|
326
316
|
installApp: "App installeren",
|
package/src/locales/no.ts
CHANGED
|
@@ -311,16 +311,6 @@ export const no: I18nTranslations = {
|
|
|
311
311
|
anyCodeWorks: "Dev-modus: Hvilken som helst kode fungerer",
|
|
312
312
|
},
|
|
313
313
|
},
|
|
314
|
-
chat: {
|
|
315
|
-
aiAssistant: "AI-assistent",
|
|
316
|
-
defaultTitle: "AI-chat",
|
|
317
|
-
newChat: "Ny chat",
|
|
318
|
-
closeChat: "Lukk chat",
|
|
319
|
-
switchToFloating: "Bytt til flytende modus",
|
|
320
|
-
switchToSidebar: "Bytt til sidefeltmodus",
|
|
321
|
-
dragToResize: "Dra for å endre størrelse",
|
|
322
|
-
howCanIHelp: "Hvordan kan jeg hjelpe deg?",
|
|
323
|
-
},
|
|
324
314
|
pwa: {
|
|
325
315
|
addToHomeScreen: "Legg til på startskjerm",
|
|
326
316
|
installApp: "Installer app",
|
package/src/locales/pl.ts
CHANGED
|
@@ -311,16 +311,6 @@ export const pl: I18nTranslations = {
|
|
|
311
311
|
anyCodeWorks: "Tryb Dev: Każdy kod działa",
|
|
312
312
|
},
|
|
313
313
|
},
|
|
314
|
-
chat: {
|
|
315
|
-
aiAssistant: "Asystent AI",
|
|
316
|
-
defaultTitle: "Chat AI",
|
|
317
|
-
newChat: "Nowy chat",
|
|
318
|
-
closeChat: "Zamknij chat",
|
|
319
|
-
switchToFloating: "Przełącz na tryb pływający",
|
|
320
|
-
switchToSidebar: "Przełącz na tryb paska bocznego",
|
|
321
|
-
dragToResize: "Przeciągnij, aby zmienić rozmiar",
|
|
322
|
-
howCanIHelp: "Jak mogę pomóc?",
|
|
323
|
-
},
|
|
324
314
|
pwa: {
|
|
325
315
|
addToHomeScreen: "Dodaj do ekranu głównego",
|
|
326
316
|
installApp: "Zainstaluj aplikację",
|
package/src/locales/pt-BR.ts
CHANGED
|
@@ -311,16 +311,6 @@ export const ptBR: I18nTranslations = {
|
|
|
311
311
|
anyCodeWorks: "Modo Dev: Qualquer código funciona",
|
|
312
312
|
},
|
|
313
313
|
},
|
|
314
|
-
chat: {
|
|
315
|
-
aiAssistant: "Assistente de IA",
|
|
316
|
-
defaultTitle: "Chat de IA",
|
|
317
|
-
newChat: "Nova conversa",
|
|
318
|
-
closeChat: "Fechar chat",
|
|
319
|
-
switchToFloating: "Mudar para modo flutuante",
|
|
320
|
-
switchToSidebar: "Mudar para modo barra lateral",
|
|
321
|
-
dragToResize: "Arraste para redimensionar",
|
|
322
|
-
howCanIHelp: "Como posso ajudar?",
|
|
323
|
-
},
|
|
324
314
|
pwa: {
|
|
325
315
|
addToHomeScreen: "Adicionar à tela inicial",
|
|
326
316
|
installApp: "Instalar aplicativo",
|
package/src/locales/ru.ts
CHANGED
|
@@ -311,16 +311,6 @@ export const ru: I18nTranslations = {
|
|
|
311
311
|
anyCodeWorks: "Режим разработки: подойдёт любой код",
|
|
312
312
|
},
|
|
313
313
|
},
|
|
314
|
-
chat: {
|
|
315
|
-
aiAssistant: "AI Ассистент",
|
|
316
|
-
defaultTitle: "AI Чат",
|
|
317
|
-
newChat: "Новый чат",
|
|
318
|
-
closeChat: "Закрыть чат",
|
|
319
|
-
switchToFloating: "Плавающий режим",
|
|
320
|
-
switchToSidebar: "Режим боковой панели",
|
|
321
|
-
dragToResize: "Потяните для изменения размера",
|
|
322
|
-
howCanIHelp: "Чем могу помочь?",
|
|
323
|
-
},
|
|
324
314
|
pwa: {
|
|
325
315
|
addToHomeScreen: "На главный экран",
|
|
326
316
|
installApp: "Установить приложение",
|
package/src/locales/sv.ts
CHANGED
|
@@ -311,16 +311,6 @@ export const sv: I18nTranslations = {
|
|
|
311
311
|
anyCodeWorks: "Dev-läge: Vilken kod som helst fungerar",
|
|
312
312
|
},
|
|
313
313
|
},
|
|
314
|
-
chat: {
|
|
315
|
-
aiAssistant: "AI-assistent",
|
|
316
|
-
defaultTitle: "AI-chatt",
|
|
317
|
-
newChat: "Ny chatt",
|
|
318
|
-
closeChat: "Stäng chatt",
|
|
319
|
-
switchToFloating: "Växla till flytande läge",
|
|
320
|
-
switchToSidebar: "Växla till sidofältsläge",
|
|
321
|
-
dragToResize: "Dra för att ändra storlek",
|
|
322
|
-
howCanIHelp: "Hur kan jag hjälpa dig?",
|
|
323
|
-
},
|
|
324
314
|
pwa: {
|
|
325
315
|
addToHomeScreen: "Lägg till på hemskärmen",
|
|
326
316
|
installApp: "Installera app",
|
package/src/locales/tr.ts
CHANGED
|
@@ -311,16 +311,6 @@ export const tr: I18nTranslations = {
|
|
|
311
311
|
anyCodeWorks: "Geliştirici Modu: Herhangi bir kod çalışır",
|
|
312
312
|
},
|
|
313
313
|
},
|
|
314
|
-
chat: {
|
|
315
|
-
aiAssistant: "AI Asistanı",
|
|
316
|
-
defaultTitle: "AI Sohbet",
|
|
317
|
-
newChat: "Yeni sohbet",
|
|
318
|
-
closeChat: "Sohbeti kapat",
|
|
319
|
-
switchToFloating: "Kayan moda geç",
|
|
320
|
-
switchToSidebar: "Kenar çubuğu moduna geç",
|
|
321
|
-
dragToResize: "Yeniden boyutlandırmak için sürükleyin",
|
|
322
|
-
howCanIHelp: "Size nasıl yardımcı olabilirim?",
|
|
323
|
-
},
|
|
324
314
|
pwa: {
|
|
325
315
|
addToHomeScreen: "Ana ekrana ekle",
|
|
326
316
|
installApp: "Uygulamayı yükle",
|
package/src/locales/zh.ts
CHANGED
|
@@ -311,16 +311,6 @@ export const zh: I18nTranslations = {
|
|
|
311
311
|
anyCodeWorks: "开发模式:任何验证码都有效",
|
|
312
312
|
},
|
|
313
313
|
},
|
|
314
|
-
chat: {
|
|
315
|
-
aiAssistant: "AI 助手",
|
|
316
|
-
defaultTitle: "AI 聊天",
|
|
317
|
-
newChat: "新对话",
|
|
318
|
-
closeChat: "关闭聊天",
|
|
319
|
-
switchToFloating: "切换到浮动模式",
|
|
320
|
-
switchToSidebar: "切换到侧边栏模式",
|
|
321
|
-
dragToResize: "拖动调整大小",
|
|
322
|
-
howCanIHelp: "有什么可以帮助您的吗?",
|
|
323
|
-
},
|
|
324
314
|
pwa: {
|
|
325
315
|
addToHomeScreen: "添加到主屏幕",
|
|
326
316
|
installApp: "安装应用",
|
package/src/types.ts
CHANGED
|
@@ -409,18 +409,6 @@ export interface I18nTranslations {
|
|
|
409
409
|
}
|
|
410
410
|
}
|
|
411
411
|
|
|
412
|
-
/** MCP Chat */
|
|
413
|
-
chat: {
|
|
414
|
-
aiAssistant: string
|
|
415
|
-
defaultTitle: string
|
|
416
|
-
newChat: string
|
|
417
|
-
closeChat: string
|
|
418
|
-
switchToFloating: string
|
|
419
|
-
switchToSidebar: string
|
|
420
|
-
dragToResize: string
|
|
421
|
-
howCanIHelp: string
|
|
422
|
-
}
|
|
423
|
-
|
|
424
412
|
/** PWA Install */
|
|
425
413
|
pwa: {
|
|
426
414
|
/** A2HS Hint */
|