This page was machine-translated. Spotted a mistake?Help improve it.
Skip to content

Översättningsguide

SnapOtter levereras med 21 språk direkt ur lådan. i18n-systemet använder en lättviktig egen körmiljö med TypeScript-genomdriven fullständighet för språkversioner och dynamisk koddelning.

Språk som stöds

CodeLanguageNative NameDirection
enEngelskaEnglishLTR
zh-CNKinesiska (förenklad)简体中文LTR
zh-TWKinesiska (traditionell)繁體中文LTR
jaJapanska日本語LTR
koKoreanska한국어LTR
esSpanskaEspañolLTR
frFranskaFrançaisLTR
itItalienskaItalianoLTR
pt-BRPortugisiska (Brasilien)Português (Brasil)LTR
deTyskaDeutschLTR
nlNederländskaNederlandsLTR
svSvenskaSvenskaLTR
ruRyskaРусскийLTR
plPolskaPolskiLTR
ukUkrainskaУкраїнськаLTR
arArabiskaالعربيةRTL
trTurkiskaTürkçeLTR
hiHindiहिन्दीLTR
viVietnamesiskaTiếng ViệtLTR
idIndonesiskaBahasa IndonesiaLTR
thThailändskaไทยLTR

Så fungerar språkigenkänning

SnapOtter använder en upplösningsordning i tre nivåer:

  1. Användarinställning - lagras i localStorage("snapotter-locale") och synkas till användarinställningarna när du är inloggad
  2. Automatisk webbläsardetektering - går igenom navigator.languages-arrayen med BCP 47-prefixmatchning
  3. Standard för instansen - administratörens miljövariabel DEFAULT_LOCALE (hämtad från GET /api/v1/config/locale)
  4. Reservspråk engelska - alltid tillgängligt

Användare kan byta språk från:

  • Jordglobsväljaren i sidfoten (desktop, alltid synlig)
  • Språkväljaren på inloggningssidan (före inloggning)
  • Avsnittet Inställningar > Allmänt (inställning per användare)
  • Språkrullgardinen i mobilens sidopanel
  • Avsnittet Inställningar > System anger standardvärdet för hela instansen (endast administratör)

Så fungerar översättningar

Alla UI-strängar finns i packages/shared/src/i18n/. Referensfilen är en.ts, som exporterar ett typat objekt med varje sträng appen använder (~1500 nycklar). Övriga språk är separata filer (t.ex. de.ts, fr.ts) som exporterar samma form.

Typen TranslationKeys använder DeepStringRecord för att acceptera vilket strängvärde som helst samtidigt som nyckelstrukturen genomdrivs. TypeScript upptäcker saknade nycklar i vilken översättningsfil som helst vid kompileringstillfället.

Endast den aktiva språkversionen laddas vid körning via dynamisk import(), vilket håller huvudbunten liten.

Använda översättningar i komponenter

tsx
import { useTranslation } from "@/contexts/i18n-context";
import { format, plural } from "@/lib/format";

function MyComponent() {
  const { t, locale, setLocale } = useTranslation();
  
  return (
    <div>
      <h1>{t.common.settings}</h1>
      <p>{format(t.settings.people.deleteConfirm, { username: "admin" })}</p>
      <p>{plural(count, t.automate.fileCount, t.automate.fileCountPlural)}</p>
    </div>
  );
}

Bidra med en översättning

Vi tar gärna emot översättnings-PR:er direkt. Du kan förbättra en befintlig språkversion eller lägga till en ny.

För att rapportera en felöversättning utan att skicka in kod kan du öppna ett GitHub Issue med språket, den felaktiga strängen och det föreslagna rättelsen.

TIP

Översättnings-PR:er kräver inget godkännande i förväg. Forka repot, gör dina ändringar och öppna en PR. Se Contributing Guide för hela PR-processen och CLA-kravet.

Så skapar eller uppdaterar du en översättning

1. Forka och klona

bash
git clone https://github.com/<your-username>/snapotter.git
cd snapotter
pnpm install

2. Kopiera referensfilen (endast nytt språk)

Hoppa över det här steget om du förbättrar en befintlig översättning.

bash
cp packages/shared/src/i18n/en.ts packages/shared/src/i18n/XX.ts

3. Översätt strängarna

Öppna din nya fil och översätt varje strängvärde. Behåll objektstrukturen och nycklarna exakt likadana.

ts
import type { TranslationKeys } from "./en.js";

export const xx: TranslationKeys = {
  common: {
    upload: "Your translation here",
    // ... translate all entries
  },
  // ... translate all sections
} as const;

Regler:

  • Översätt inte objektnycklar, bara strängvärden
  • Behåll as const i slutet
  • Importera TranslationKeys från ./en.js och typa din export
  • Behåll {variable}-platshållare exakt som de är
  • Arrayer (rotatingPhrases, progressMessages) måste ha samma antal poster
  • Översätt inte: SnapOtter, JPEG, PNG, WebP, EXIF, API och andra tekniska termer

4. Registrera språkversionen (endast nytt språk)

Lägg till din språkversion i SUPPORTED_LOCALES i packages/shared/src/i18n/index.ts:

ts
{ code: "xx", name: "Language Name", nativeName: "Native Name", dir: "ltr" },

5. Verifiera

bash
pnpm typecheck    # catches missing or mistyped keys
pnpm lint         # formatting check
pnpm dev          # manually verify strings appear correctly

6. Skicka in

Öppna en PR mot main med en titel som feat(i18n): add Swedish translation eller fix(i18n): correct German typos. CLA-boten ber dig signera vid ditt första bidrag.

Lägga till nya översättningsnycklar

När du lägger till en ny funktion som behöver nya UI-strängar:

  1. Lägg till de nya nycklarna i en.ts först (referensfilen)
  2. Kör pnpm typecheck - varje språkfil misslyckas om den nya nyckeln saknas
  3. Lägg till den nya nyckeln i alla språkfiler (använd engelska som tillfälligt reservspråk)

Konfiguration

Ange instansens standardspråk via en miljövariabel:

yaml
DEFAULT_LOCALE: "de"  # German as the default for all new users

Filreferens

FilePurpose
packages/shared/src/i18n/en.tsEngelska strängar (referensspråk, ~1500 nycklar)
packages/shared/src/i18n/index.tsSUPPORTED_LOCALES, loadTranslations(), typexporter
packages/shared/src/i18n/<locale>.tsÖversättningsfiler per språk
apps/web/src/contexts/i18n-context.tsxI18nProvider, useTranslation()-hook
apps/web/src/lib/format.tsformat()-, plural()-, formatFileSize()-hjälpfunktioner
apps/api/src/routes/config.tsGET /api/v1/config/locale publik ändpunkt

Översätta webbplatsen, dokumentationen och API-referensen

De 21 språk som stöds ovan gäller appen. Den publika webbplatsen (snapotter.com), den här dokumentationssidan och REST-API-referensen är också översatta till alla 21 språk, av en separat hash-styrd pipeline som återanvänder samma verktygsnamn och beskrivningar från packages/shared/src/i18n, så att terminologin förblir konsekvent överallt.

Maskinöversatt som standard

Varje icke-engelsk sida på webbplatsen och i dokumentationen är maskinöversatt i första omgången (av en Claude Code-session, inte en tredjepartstjänst) och bär en liten, avfärdbar banner som talar om det, med en länk tillbaka hit. Det är ett medvetet val: det levererar alla 21 språk snabbt och ärligt, och bjuder sedan in gemenskapen att förfina de sidor som betyder mest. Maskinöversättning för fram betydelsen; mänsklig granskning gör att den läses naturligt.

Så avgör pipelinen vad som ska översättas

Varje översättningsbar enhet av den engelska källan hashas, och hashen lagras intill sin översättning. Vid varje körning gör pipelinen följande:

  • översätter varje enhet som ännu inte har någon översättning,
  • hoppar över varje enhet vars lagrade hash fortfarande matchar den engelska källan,
  • återöversätter en maskin-enhet när dess engelska källa ändras,
  • och flaggar en mänskligt förfinad enhet som stale (behöver granskning) när dess engelska källa ändras, i stället för att skriva över ditt arbete.

Förfina en webböversättning via PR

Du förbättrar en översättning av webbplatsen, dokumentationen eller API-referensen på samma sätt som du förbättrar en språkversion i appen: genom att redigera den genererade filen och öppna en PR.

  1. Hitta den genererade översättningen för ditt språk:
    • UI-strängar för webbplatsen: apps/landing/src/i18n/<locale>.json
    • en dokumentationssida: apps/docs/<locale>/**.md
    • API-referensen: apps/api/src/openapi.<locale>.yaml
  2. Redigera texten. Behåll kod, länkar, {placeholders} och alla ⸤I18N…⸥-markeringar exakt som de är; pipelinens validator avvisar en översättning som tar bort eller kastar om dem.
  3. Öppna en PR. Att redigera en enhet flippar dess ursprung från machine till human, så att pipelinen aldrig skriver över den vid en senare körning. Om den engelska källan ändras därefter flaggas din enhet som stale för granskning i stället för att tyst ersättas.

För att rapportera en felöversättning utan att skicka in kod kan du öppna ett GitHub Issue med sidans URL, språket, den felaktiga texten och ditt föreslagna rättelse.

TIP

Underhållarna kör översättningspipelinen; du behöver ingen API-nyckel för att bidra. Redigera bara den genererade filen och öppna en PR. Se scripts/i18n/README.md för hur pipelinen körs.