Hvad er i18n?

Internationalisering (i18n) er processen med at designe software, så den kan tilpasses forskellige sprog og regioner uden at ændre din kode. Kælenavnet "i18n" kommer af, at der er 18 bogstaver mellem "i" og "n" i internationalisering.

Tænk på i18n som grundlaget for:

  • Lokalisering (l10n): Oversættelse og tilpasning af dit indhold til et specifikt marked.
  • Globalisering (g11n): Koordinering af produktberedskab og operationer på tværs af markeder.

I praksis handler i18n om at sikre, at din app kan håndtere:

  • Tekst på et hvilket som helst sprog
  • Datoer, klokkeslæt, tal og valutaer i det rigtige format
  • Pluraliseringsregler, der matcher lokal grammatik
  • Højre-mod-venstre-layouts (som arabisk eller hebraisk)

 

Hvorfor i18n er vigtig

Investering i i18n på forhånd giver håndgribelige fordele for dine ingeniør- og produktteams:

  • Lavere lokaliseringsomkostninger: Det er nemmere at udtrække og erstatte strenge, når oversættelseslogik er indbygget fra starten.
  • Hurtigere udvikling: Delt infrastruktur til administration af strenge reducerer fremtidig omarbejde.
  • Bedre brugeroplevelse: Brugere ser indhold på deres eget sprog, formateret på måder, der føles naturlige.
  • Skalerbarhed: Apps kan lanceres på nye markeder med færre kodeændringer.

 

i18n implementeringsmønstre i moderne apps

Nedenfor er nogle almindelige mønstre for implementering af i18n i produktionsapps. Vi vil gennemgå React (frontend), iOS og Android.

Uanset platformen kommer oversættelser normalt fra et oversættelsesstyringssystem (TMS) som Smartling som JSON eller ressourcefiler. Disse filer indlæses derefter af din app under kørsel via et i18n-framework eller en native lokaliserings-API, hvilket sikrer, at de korrekte strenge vises for brugerens sprog eller lokalitet.

 

Frontend (React)

Moderne React-apps bruger typisk et dedikeret i18n-bibliotek. To af de mest populære er i18next og FormatJS, som begge er framework-agnostiske. I React er deres respektive implementeringer react-i18next (funktions- og hook-baseret) og react-intl (komponent- og hook-baseret, bygget på ICU MessageFormat). Begge integreres problemfrit med virksomhedens pipelines og håndterer pluralisering, variabler og lokalitetsbevidst formatering.

 

1. Reager med i18next + react-i18next

i18next er et af de mest populære JavaScript i18n-biblioteker, og når det parres med react-i18next- bindingerne, giver det React-apps en kraftfuld, hook-venlig API til indlæsning og gengivelse af oversættelser.

I eksemplet nedenfor gennemgår vi et almindeligt i18n-mønster for virksomheder. Vi definerer oversættelsesfiler, initialiserer i18next ved appens indgangspunkt og gengiver derefter oversættelser i komponenter. Denne tilgang fungerer på tværs af frameworks, integreres problemfrit med de fleste oversættelsesstyringssystemer (TMS) og skalerer godt, efterhånden som din app vokser – uanset om du viser statiske strenge eller dynamiske, variabeldrevne meddelelser som f.eks. antal.

 

Eksempel på i18n-mønster: i18next + reacti18next

Du vil sandsynligvis modtage indhold som JSON-filer fra dit oversættelsesstyringssystem. JSON-fileksemplet nedenfor viser, hvordan oversættelser til engelsk gemmes. Hver post har en unik nøgle, og flertalsformer defineres separat, så biblioteket kan vælge den rigtige baseret på den optælling, du sender. Dit TMS vil generere en matchende fil for hvert understøttede sprog.

 

{

  "welcome": "Welcome",

  "visits_one": "Du har besøgt siden {{count}}} gang.",

  "visits_other": "Du har besøgt siden {{count}} gange."

}

 

Dernæst ser du et eksempel på, hvordan du konfigurerer i18next, så den ved, hvilke sprog din app understøtter, hvor den finder oversættelserne, og hvad du skal gøre, hvis en oversættelse mangler. Denne opsætningsfil køres én gang, når din app starter (ofte i indgangsfilen som index.js eller main.tsx) så oversættelserne er klar, før nogen brugergrænseflade gengives. Centralisering af konfigurationen på ét sted sikrer, at din lokaliseringslogik er ensartet på tværs af din app.

 

importer i18next fra 'i18next';

importer { initReactI18next } fra 'react-i18next';

import en from './locales/en/translation.json';

importer fr fra './locales/fr/translation.json';

 

const locale = 'fr'; // i produktion, opløses dynamisk

 

i18next

  .use(initReactI18next)

  .init({

    lng: locale,

    fallbackLng: 'en',

    ressourcer: {

      en: { translation: en },

      fr: { oversættelse: fr }

    },

    interpolation: { escapeValue: false }

  });

 

eksporter standard i18next;

 

Når i18next er initialiseret, kan du bruge det hvor som helst i din app. I eksemplet nedenfor henter useTranslation- hooken t- funktionen, som bruger en nøgle og valgfrie variabler til at gengive den rigtige streng. Når du bruger count som en variabel, vælger i18next automatisk den korrekte flertalsform baseret på oversættelsesfilen.

 

importer { useTranslation } fra 'react-i18next';

import './i18n';

 

eksporter standardfunktionen App() {

  const { t } = brugOversættelse();

  konstant antal = 3;

 

  retur (

    <>

      <h1>{t('welcome')}</h1>

      <p>{t('besøg', { antal })}</p>

    </>

  );

}

 

2. Reager med FORmatJS + react-intl

react-intl er en del af FormatJS- økosystemet og tilbyder en komponentbaseret tilgang til i18n i React. Den er bygget på ICU MessageFormat-standarden, så du får indbygget pluralisering, dato-/talformatering og alternativ valgmulighed for lokalitet.

I eksemplet nedenfor opsætter vi oversættelsesfiler, pakker appen ind i en IntlProvider og gengiver lokaliseret tekst ved hjælp af FormattedMessage. Denne tilgang er velegnet til teams, der ønsker en deklarativ, komponentdrevet stil til håndtering af i18n i React.

 

Eksempel på i18n-mønster: FormatJS + react-intl

JSON-filen nedenfor indeholder oversættelser ved hjælp af ICU MessageFormat-syntaks, som placerer plurallogik i selve strengen. Dette holder alle sprogregler samlet ét sted og giver oversætterne fuld kontrol over grammatikken uden udviklerindgriben. Dit TMS administrerer disse filer pr. lokalitet.

 

{

  "welcome": "Welcome",

{% raw %} "visits": "Du har besøgt {count, plural, one {# time} other {# times}}." end_raw %}

Dernæst ser du et eksempel på, hvordan du pakker din app ind i IntlProvider- komponenten. Dette er en engangsopsætning, som normalt udføres i en rodkomponent som Root.tsx eller index.jsx. Det gør den aktive lokalitet og dens beskeder tilgængelige i hele din app, så enhver komponent kan bruge dem uden ekstra import.

 

importer { IntlProvider } fra 'react-intl';

import en from './locales/en.json';

importer fr fra './locales/fr.json';

 

const MESSAGES = { en, fr };

const locale = 'fr';

 

eksporter standardfunktionen Root() {

  retur (

    <IntlProvider locale={locale} messages={MESSAGES[locale]}>

      <App />

    </IntlProvider>

  );

}



Til sidst kan du læse nedenfor for at se, hvordan FormattedMessage- komponenten slår en oversættelse op efter dens ID og håndterer pluralisering automatisk. Alt du skal bestå er optællingen, og biblioteket anvender de korrekte sprogregler fra din JSON-fil.

 

importer { FormattedMessage } fra 'react-intl';

 

eksporter standardfunktionen App() {

  konstant antal = 3;

 

  retur (

    <>

      <h1><FormattedMessage id="welcome" defaultMessage="Welcome" /></h1>

      <p><FormattedMessage id="visits" values={{ count }} /></p>

    </>

  );

}

 

Et par yderligere tips til brug i produktionen:

  • Lokalkilde: I rigtige apps skal du bestemme lokaliteten centralt (f.eks. fra en URL som /fr/*, brugerens profil eller en serverleveret indstilling) og sende den til <IntlProvider>.
  • Beskedorganisation: For skalering, opdel beskedfiler efter domæne eller funktion (f.eks. auth.json, dashboard.json) og flette dem sammen for den aktive lokalitet.
  • Reserver: defaultMessage er dit sikkerhedsnet under udrulningen – hold den på dit kildesprog.
  • Asynkron indlæsning (valgfrit): For store bundter skal du dynamisk importere meddelelsesfiler pr. landestandard (kodeopdeling) før rendering af<IntlProvider>.



iOS

iOS giver dig solide lokaliseringsværktøjer lige fra starten, men ren skalering til mange lokaliteter kræver en gennemtænkt implementering af bedste praksis for i18n. Ellers kan du uden en klar struktur ende med duplikerede nøgler, inkonsekvent formatering og oversættelsesfiler, der bliver besværlige at vedligeholde. Nøglen er at træffe et par strukturelle beslutninger tidligt, så din lokalisering forbliver organiseret og nem at udvide, efterhånden som nye markeder tilføjes.

 

Tip 1: Organiser ressourcer på en skalerbar måde

Et godt sted at starte er med String Catalogs (.xcstrings) i Xcode 15 og nyere, eller .strings/.stringsdict filer, hvis du bruger en ældre opsætning. Disse fungerer godt sammen med et TMS, som normalt sender dig oversættelser i XLIFF-format. Du kan importere dem direkte til dit katalog, og systemet vil håndtere det hårde arbejde med at flette og administrere dem.

Du vil sandsynligvis finde det nemmere at holde orden i tingene, hvis du organiserer kataloger efter funktion eller modul. Mindre, målrettede filer gør det nemmere at finde nøgler, gennemgå ændringer og overdrage arbejde til oversættere. Her er et eksempel på, hvordan du måske vil organisere dem:

 

Ressourcer

  i18n/

    Aut.xcstrenge

    Checkout.xcstrings

    Profil.xcstrenge



Tip 2: Håndter pluralisering i kataloget, ikke i koden

Pluralisering er et andet sted, hvor struktur betaler sig. Det er bedre at definere alle flertalsregler i kataloget i stedet for i Swift, så din kode kun sender variabler, og den rigtige sætning vælges automatisk for hvert sprog. Sådan her kan det se ud i kataloget:

 

Nøgle: ulæste_beskeder

Format: Flertal

En: "%d ulæst besked"

Andet: "%d ulæste beskeder"

 

Og sådan kan du bruge det i Swift:

 

lad ulæsteAntal = 3

lad format = String(lokaliseret: "ulæste_beskeder")

lad besked = String.localizedStringWithFormat(format, ulæsteAntal)

// "3 ulæste beskeder"

 

På denne måde indkoder du ikke grammatikken i koden, og oversætterne kan få detaljerne korrekte for hvert sprog.

 

Tip 3: Centraliser formatering for tal, datoer og valutaer

Du bør også centralisere formateringen af tal, dato og valuta, så alle dele af appen føles ensartede. Et fælles forsyningsselskab eller en fælles tjeneste kan hjælpe med det. Her er et simpelt eksempel med Swifts moderne FormatStyle API:

 

lejepris = 19,99

lad display = price.formatted(.currency(kode: "EUR"))

// "19,99 €" eller "19,99 €" afhængigt af lokalitet

 

Ved at holde dine strengressourcer organiseret, håndtere pluralisering i kataloget og centralisere al din lokalitetsbevidste formatering, sætter du din iOS-app op til at vokse uden at skabe ekstra vedligeholdelsesarbejde. Når disse fremgangsmåder er på plads, bliver processen med at tilføje nye sprog langt mere forudsigelig – og meget mindre stressende. Lad os nu se på Android, som tilbyder sine egne indbyggede lokaliseringsværktøjer.

 

Android

Androids ressourcesystem er allerede designet med lokalisering i tankerne, men det kræver en vis planlægning at holde det vedligeholdbart på tværs af mange sprog. Hvis du opbevarer alt i én stor fil eller spreder grammatikregler i koden, kan det hurtigt blive rodet. Prioriter i stedet en segmenteret organisering af filer, definer alle grammatikregler i XML, og sørg for, at din formatering og dine layouts fungerer for alle de skrivesystemer, du planlægger at understøtte.

 

Tip 1: Hold ressourcerne organiseret efter funktion

For de fleste teams vil oversættelserne komme fra et TMS som XLIFF-filer. Du importerer disse til res/values -mapperne for hver lokalitet, og Android sørger for at matche de rigtige strenge med brugerens sprog.

At opdele dine ressourcer i separate filer efter funktion er en simpel måde at gøre livet lettere på. Mindre filer gør det hurtigere at gennemgå ændringer og hjælper med at undgå fletningskonflikter.

 

app/src/main/res/

  values/strings_auth.xml

  values/strings_checkout.xml

  values/plurals_checkout.xml

 

Tip 2: Definer grammatikregler i ressourcer, ikke i kode

Ligesom i iOS er pluralisering en af de ting, der bedst håndteres i ressourcer, så oversættere kan tilpasse det til hvert sprog uden at du skal ændre kode. Her er et eksempel på en flertalsressource på engelsk:

 

<plurals name="checkout_cart_items_count">

    <item quantity="one">%1$d item</item>

    <item quantity="other">%1$d varer</item>

</plurals>

 

Og sådan her bruger du det i Kotlin:

 

val msg = resources.getQuantityString()

    R.plurals.checkout_cart_items_count, tælle, tælle

)

 

På denne måde forbliver vores kode ren, og Android vælger automatisk den rigtige formular baseret på lokaliteten.

 

Tip 3: Brug lokalitetsbevidst formatering 

For layouts er det en god vane at bruge start og slut i stedet for venstre og højre , så de tilpasser sig højre-mod-venstre-sprog som arabisk eller hebraisk:

 

<LinearLayout

    android:paddingStart="16dp"

    android:paddingEnd="16dp"

    android:layout_width="match_parent"

    android:layout_height="wrap_content">

</LinearLayout>

 

Og når du formaterer tal eller valutaer, skal du indsætte appens aktuelle sprogstandard, så alt ser ensartet ud:

 

val appLocale = LocaleListCompat.getAdjustedDefault()[0] ?: Locale.getDefault()

val pris = NumberFormat.getCurrencyInstance(appLocale).format(1234.56)

// "1.234,56 kr." eller "1 234,56 €"

 

I sidste ende handler det meste om at lade platformen gøre det hårde arbejde, når man får Android i18n rigtigt. Ved at holde al tekst i ressourcer, strukturere disse ressourcer med lokalitetsspecifikke mapper og indbygge RTL- og lokalitetsbevidst formatering fra dag ét, undgår du de almindelige fælder, der gør lokalisering skrøbelig. Mange af disse principper afspejler iOS' bedste praksis, men Androids ressourcekvalificeringssystem betyder, at du ofte kan understøtte nye sprog ved blot at tilføje de rigtige filer. Hvis det gøres godt, bliver skalering til nye lokaliteter en forudsigelig og lavanstrengende proces.

 

Almindelige i18n-faldgruber

Desværre støder selv veludviklede systemer sommetider på problemer, der kan undgås. Tabellen nedenfor beskriver nogle af de mest almindelige fejltrin, hvorfor de forårsager problemer, og hvordan man kan forebygge dem. Betragt dette som en hurtig reference, du kan bruge til at kontrollere din egen opsætning inden afsendelse.

 

Fejl

Sådan undgår du det

Hardkodede strenge

Udpak al brugervendt tekst til ressourcefiler eller oversættelsesnøgler.

Forudsat at al tekst er fra venstre mod højre

Test layouts med højre-mod-venstre-sprog som arabisk eller hebraisk.

Forsømmelse af pluralisering

Brug biblioteker, der understøtter flertalsregler (f.eks. ICU-format, i18next).

Ikke-lokaliserede enheder eller formater

Brug lokalitetsbevidst formatering (f.eks. Intl.NumberFormat, Intl.DateTimeFormat).

Springer over tekstudvidelsestjek

Test med pseudo-lokaler for at simulere længere oversættelser.

Ufuldstændig strengudtrækning

Brug pseudo-lokaliteter i staging til at afdække manglende eller utaggede strenge.

 

 

Forberedelse til lokalisering i stor skala

Når din app er konfigureret til internationalisering, er næste skridt at gøre lokaliseringen så effektiv og vedligeholdelsesfri som muligt. Et par automatiseringsværktøjer og arbejdsgange kan tage dig fra "vi kan oversætte" til "vi kan hurtigt udrulle nye sprog uden ekstra udviklingsbyrde". Overvej:

  • Brug af et oversættelsesstyringssystem (TMS) med en API i virksomhedsklassen, som f.eks. Smartling, til at synkronisere oversættelsesfiler og administrere arbejdsgange for gennemgang.
  • Automatisering af strengudtrækning og -levering ved hjælp af din CI/CD-pipeline.
  • Brug af AI-værktøjer (som Smartlings AI Hub) til hurtige førstegangsoversættelser med indbyggede kvalitetskontroller som f.eks. håndtering af fallbacks og forebyggelse af hallucinationer.

 

Sidste tanker

Internationalisering er en grundlæggende praksis for ethvert produkt, der bliver globalt, og jo tidligere du implementerer det, jo færre hovedpiner vil du have senere. Kombinér solide i18n-praksisser med automatisering af oversættelser og testworkflows, og dit team vil være godt rustet til at levere internationalt klar software hurtigere og mere sikkert.

Vil du gå dybere? Tjek Smartlings ud Webinar om Global Ready-konferencen om i18n strategi i AI'ens tidsalder.

Hvorfor ikke oversætte mere intelligent?

Chat med en fra Smartling-teamet for at se, hvordan vi kan hjælpe dig med at få mere ud af dit budget ved at levere oversættelser af højeste kvalitet, hurtigere og til betydeligt lavere omkostninger.
Cta-Card-Side-Image