# Contributing translations Thanks for helping translate MediaGo! This guide walks you through adding a new language from scratch, with a live-preview workflow so you can iterate without rebuilding the app. ## TL;DR ```shell git clone https://github.com/caorushizi/mediago.git cd mediago pnpm install pnpm deps:download pnpm dev:electron ``` 1. Copy `packages/shared/common/src/i18n/resources/en.ts` to `.ts`, translate every value. 2. Register the new locale in the shared resources, resolver, UI dropdown, and browser extension (see below). 3. Open **Settings → Language**, pick your locale, and iterate. Vite HMR reflects edits in the running app within a second. 4. Open a PR — we review and merge. ## Where strings live - **Main app UI** (desktop + self-hosted web): `packages/shared/common/src/i18n/resources/{en,it,zh}.ts` - **Browser extension** (separate, smaller catalog): `packages/mediago-extension/src/i18n/resources/{en,it,zh}.ts` Resources are plain TypeScript modules — each file exports a flat object of `key: "translation"` pairs. Keys are shared across languages; only values change. ## Adding a new language end-to-end Example: French (`fr`). Adjust the code to whichever language you're adding. ### 1. Create the resource file Copy `en.ts` to `fr.ts` in the same directory and translate every **value**. Leave all keys untouched: ```ts // packages/shared/common/src/i18n/resources/fr.ts export const fr = { // ...translated values... followSystem: "Système", chinese: "中文", english: "English", french: "Français", // add your language's own name displayLanguage: "Langue", // ... } as const; ``` Don't forget to add the new `french: "Français"` key to **every** resource file (`en.ts`, `it.ts`, `zh.ts`, and your new `fr.ts`) so the Settings dropdown can render it in each language. ### 2. Register the resource Core app registration: **`packages/shared/common/src/i18n/resources/index.ts`** — import the new locale and add it to both exports: ```ts import { fr } from "./fr"; // ... export const i18nResources = { en, it, zh, fr } as const; export const SUPPORTED_LANGUAGES = ["en", "it", "zh", "fr"] as const; export { en, it, zh, fr }; ``` **`packages/shared/common/src/i18n/config.ts`** — widen the `resolveAppLanguage` return type and the check inside: ```ts export type ResolvedAppLanguage = "zh" | "en" | "it" | "fr"; export function resolveAppLanguage( language: string | undefined, systemLocale: string | undefined, ): ResolvedAppLanguage { if ( language === "zh" || language === "en" || language === "it" || language === "fr" ) { return language; } // ...existing fallback... } ``` If the new locale should follow the OS/browser locale automatically, add the matching `systemLocale` prefix check in the same function. **`packages/shared/common/src/types/index.ts`** — extend the `AppLanguage` enum: ```ts export enum AppLanguage { System = "system", ZH = "zh", EN = "en", FR = "fr", } ``` **`apps/ui/src/App.tsx`** — if Ant Design ships a locale for your language, import it and include it in `getAntdLocale`. Otherwise, explicitly fall back to `enUS` for Ant Design components while your app strings still use your translated resource file. ### 3. Add the Settings dropdown option **`apps/ui/src/pages/setting-page/index.tsx`** — inside the **Language** `