@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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@djangocfg/i18n",
3
- "version": "2.1.584",
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.584",
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,3 @@
1
+ export { LOCALES, resolveLocale, type Dictionaries, type Locale } from './locales'
2
+ export { createCopy, type CopyKit } from './createCopy'
3
+ export { fill, plural, type FillValues, type PluralCopy } from './format'
@@ -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ę",
@@ -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 */