App-lokalisering: Bästa praxis – En komplett guide för utvecklare
Du har byggt en fantastisk app. Din kod är ren, dina funktioner är stabila och dina engelsktalande användare älskar den. Men du lämnar 75 % av potentiella användare på bordet genom att inte stödja deras språk.
App-lokalisering handlar inte bara om översättning – det handlar om att få din app att kännas inhemsk för användare runt om i världen. En väl-lokaliserad app kan öka nedladdningar med 128 % och intäkter med över 26 % per marknad, enligt Distomos forskning om app-lokalisering.
I denna omfattande guide lär du dig allt du behöver veta om att lokalisera mobila och webbappar: från att skydda variabla platshållare till att hantera pluralisering, datumformat och kulturella nyanser.
Vad är App-lokalisering (och varför det spelar roll)
Lokalisering går bortom översättning. Det handlar om att anpassa din app till en specifik lokal, inklusive:
- Språköversättning (uppenbart men bara början)
- Kulturell anpassning (färger, bilder, symboler betyder olika saker)
- Formatkonventioner (datum, nummer, valutor)
- Laglig efterlevnad (GDPR i EU, olika användarvillkor)
- Betalningsmetoder (Alipay i Kina, UPI i Indien)
Verklig påverkan
Fallstudie: Duolingo
- Lokaliserade appen till 40+ språk
- Såg 300 % ökning i användarförvärv på icke-engelska marknader
- App Store-betyg förbättrades med 0,8 stjärnor i genomsnitt på lokaliserade marknader
Fallstudie: Spotify
- Lade till stöd för hindi och tamil i Indien
- Användarbasen växte 200 % på 6 månader
- Blev #1 musikstreamingapp i regionen
Den tekniska grunden: i18n vs L10n
Innan vi dyker in, låt oss förtydliga två termer du kommer se överallt:
i18n (Internationalisering) Att förbereda din kodbas för att stödja flera språk. Detta inkluderar:
- Externalisera strängar (ingen hårdkodad text)
- Använda platshållarvariabler
- Stöd för RTL (höger-till-vänster) språk
- Designa flexibla layouter
L10n (Lokalisering) Att faktiskt översätta och anpassa innehåll för specifika lokaler:
- Översätta UI-strängar
- Formatera datum/nummer
- Tillhandahålla locale-specifika bilder
- Justera kulturella referenser
*Tänk så här:
- i18n = Bygga infrastrukturen (du gör detta en gång)
- L10n = Lägga till nya språk (du gör detta upprepat)
Steg 1: Internationalisera din kodbas
iOS-appar (.strings-filer)
iOS använder .strings-filer för lokalisering:
en.lproj/Localizable.strings:
/* Inloggningsskärm */
"welcome_message" = "Välkommen tillbaka!";
"login_button" = "Logga in";
"forgot_password" = "Glömt lösenord?";
/* Profilskärm */
"edit_profile" = "Redigera profil";
"logout_button" = "Logga ut";
I din Swift-kod:
// Bra - Localizable
welcomeLabel.text = NSLocalizedString("welcome_message", comment: "Välkomstmeddelande på inloggningsskärm")
// Dåligt - Hårdkodat (gör inte detta)
welcomeLabel.text = "Välkommen tillbaka!"
Android-appar (strings.xml)
Android använder XML-resursfiler:
res/values/strings.xml (engelska som standard):```xml
**res/values-es/strings.xml (spanska):**```xml
<resources>
<string name="welcome_message">¡Bienvenido de nuevo!</string>
<string name="login_button">Iniciar sesión</string>
<string name="items_count">Tienes %d artículos</string>
</resources>
I din Kotlin/Java-kod:
// Bra
binding.welcomeText.text = getString(R.string.welcome_message)
// Dåligt - Hårdkodat
binding.welcomeText.text = "Välkommen tillbaka!"
React/Webbappar (i18n JSON)
Moderna webbappar använder JSON-filer med bibliotek som i18next eller react-intl:
locales/en.json:
{
"welcome_message": "Välkommen tillbaka!",
"login_button": "Logga in",
"items_count": "Du har {{count}} objekt",
"greeting": "Hej, {{name}}!"
}
locales/es.json:
{
"welcome_message": "¡Bienvenido de nuevo!",
"login_button": "Iniciar sesión",
"items_count": "Tienes {{count}} artículos",
"greeting": "¡Hola, {{name}}!"
}
I dina React-komponenter:
import { useTranslation } from 'react-i18next';
function LoginScreen() {
const { t } = useTranslation();
return (
<div>
<h1>{t('welcome_message')}</h1>
<button>{t('login_button')}</button>
</div>
);
}
}
Steg 2: Hantera variabelplaceholder korrekt
Den vanligaste lokaliseringssatsen är att förstöra variabelplaceholder under översättning.
Exempel på strängformatering
iOS (Swift):
// Enkel variabel
let message = String(format: NSLocalizedString("greeting", comment: ""), userName)
// "greeting" = "Hello, %@!";
// Flera variabler
let status = String(format: NSLocalizedString("order_status", comment: ""), orderId, itemCount)
// "order_status" = "Order #%@ contains %d items";
Android (Kotlin):
// Enkel variabel
val message = getString(R.string.greeting, userName)
// <string name="greeting">Hello, %s!</string>
// Flera variabler
val status = getString(R.string.order_status, orderId, itemCount)
// <string name="order_status">Order #%1$s contains %2$d items</string>
React (i18next):
// Enkel variabel
t('greeting', { name: userName })
// "greeting": "Hello, {{name}}!"
// Flera variabler
t('order_status', { orderId: '12345', count: 5 })
// "order_status": "Order #{{orderId}} contains {{count}} items"
Vanliga placeholder-misstag
❌ Misstag 1: Översättaren tar bort placeholder
// Före översättning
"welcome": "Welcome, {{name}}!"
// Dålig översättning (placeholder borttagen)
"welcome": "欢迎!" // Namnvariabeln förlorad
// Korrekt
"welcome": "欢迎,{{name}}!"
❌ Misstag 2: Fel placeholder-format
<!-- Före -->
<string name="items">You have %d items</string>
<!-- Dåligt (fel format) -->
<string name="items">Vous avez %s articles</string> <!-- %s istället för %d -->
<!-- Korrekt -->
<string name="items">Vous avez %d articles</string>
❌ Misstag 3: Bytt placeholder-ordning
// Före
"date_range": "From %1$s to %2$s"
// Dåligt (ordningen spelar roll!)
"date_range": "De %2$s à %1$s" // Bytt utan positionsmarkörer
// Korrekt (använd positionsargument)
"date_range": "De %1$s à %2$s"
Steg 3: Bemästra pluraliseringsregler
Engelska har enkla pluraler: 1 item, 2 items. Enkelt, eller hur? Fel. Andra språk har komplex pluralisering:
- Arabiska: 6 pluralformer (zero, one, two, few, many, other)
- Ryska: 3 pluralformer baserat på sista siffran
- Japanska: Ingen pluraldistinktion
- Polska: Komplexa regler baserat på siffror som slutar på specifika siffror
iOS Pluralisering (.stringsdict)
Localizable.stringsdict:
<?xml version="1.0" encoding="UTF-8"?>
<plist version="1.0">
<dict>
<key>items_count</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@items@</string>
<key>items</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>zero</key>
<string>No items</string>
<key>one</key>
<string>One item</string>
<key>other</key>
<string>%d items</string>
</dict>
</dict>
</dict>
</plist>
Android Pluralisering (plurals.xml)
res/values/strings.xml:
<plurals name="items_count">
<item quantity="zero">No items</item>
<item quantity="one">One item</item>
<item quantity="other">%d items</item>
</plurals>
Användning i Kotlin:
val count = 5
val text = resources.getQuantityString(R.plurals.items_count, count, count)
// Output: "5 items"
React Pluralisering (i18next)
locales/en.json:
{
"items_count": "{{count}} item",
"items_count_plural": "{{count}} items",
"items_count_zero": "No items"
}
Användning:
t('items_count', { count: 0 }) // "No items"
t('items_count', { count: 1 }) // "1 item"
t('items_count', { count: 5 }) // "5 items"
Steg 4: Hantera datum, tider och nummer
Aldrig hårdkoda datum-/nummerformat. De varierar dramatiskt beroende på locale:
Datumformatering
US (en-US): 12/31/2025 (MM/DD/YYYY) UK (en-GB): 31/12/2025 (DD/MM/YYYY) Japan (ja-JP): 2025/12/31 (YYYY/MM/DD) Tyskland (de-DE): 31.12.2025 (DD.MM.YYYY)
iOS (Swift):
let date = Date()
let formatter = DateFormatter()
formatter.dateStyle = .medium
formatter.locale = Locale.current
print(formatter.string(from: date))
// US: "Jan 15, 2025"
// Tyskland: "15. Jan. 2025"
// Japan: "2025/01/15"
Android (Kotlin):
val date = Date()
val format = DateFormat.getDateInstance(DateFormat.MEDIUM, Locale.getDefault())
println(format.format(date))
React (JavaScript):
const date = new Date();
const formatted = new Intl.DateTimeFormat(locale, {
year: 'numeric',
month: 'long',
day: 'numeric'
}).format(date);
// en-US: "January 15, 2025"
// fr-FR: "15 janvier 2025"
// ja-JP: "2025年1月15日"
Formatering av nummer och valuta
Nummer:
- USA: 1,234,567.89
- Tyskland: 1.234.567,89
- Indien: 12,34,567.89 (lakh-system)
iOS:
let number = 1234567.89
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
formatter.locale = Locale.current
print(formatter.string(from: NSNumber(value: number))!)
Valuta:
let price = 99.99
let formatter = NumberFormatter()
formatter.numberStyle = .currency
formatter.locale = Locale(identifier: "ja-JP")
print(formatter.string(from: NSNumber(value: price))!)
// Utdata: "¥100" (avrundat i japanska yen)
Steg 5: Översätt dina lokaliseringfiler
Nu kommer den faktiska översättningen. Du har flera alternativ:
Alternativ 1: Manuell översättning (Långsam men exakt)
Anlita modersmålstalare eller använd ett översättningsbyrå:
✅ Fördelar:
- Hög kvalitet
- Kulturella nyanser förstås
- Mänsklig granskning
❌ Nackdelar:
- Dyrt (0,10–0,25 USD per ord)
- Långsamt (veckor för stora appar)
- Svårt att uppdatera ofta
Alternativ 2: Maskinöversättning + granskning (Balanserat)
Använd AI-översättningsverktyg och låt sedan modersmålstalare granska:
✅ Fördelar:
- Snabbt (minuter istället för veckor)
- Kostnadseffektivt (10–50 USD per miljon tecken jämfört med tusentals för mänsklig översättning)
- Bra för initial lansering
- Perfekt för iteration
⚠️ Var uppmärksam på:
- Teknisk terminologi (granska noga)
- Konsistens i varumärkesröst
- Kulturell lämplighet
Alternativ 3: Crowd-sourcing översättning (Community-driven)
Låt dina användare översätta (som Wikipedia):
✅ Fördelar:
- Gratis eller mycket billigt
- Community-engagemang
- Täcker obskyra språk
❌ Nackdelar:
- Kvaliteten varierar vilt
- Långsamt för nya strängar
- Kräver moderering
Steg 6: Testa på alla språk
Översätt inte bara och skicka. Testa noggrant:
Layouttestning
Textutvidgning är verkligt:
Engelska: "Settings" (8 tecken) Tyska: "Einstellungen" (14 tecken – 75 % längre!) Finska: "Asetukset" (9 tecken)
Testa dina layouter med:
1. Längsta språket (vanligtvis tyska/finska)
2. Kortaste språket (vanligtvis kinesiska/japanska)
3. RTL-språk (arabiska/hebreiska)
4. Specialtecken (polska ą, ż, ć)
Funktions-testning
- Tryck på alla knappar på varje språk (se till att de fungerar)
- Fyll i formulär (felmeddelanden ska också vara översatta)
- Testa kantfall (0 objekt, 1 objekt, många objekt för pluraler)
- Kontrollera notiser (push-notiser behöver översättning)
Pseudolokalisering
Innan riktig översättning, använd pseudolokalisering för att fånga buggar:
"Settings" → "[!!! Šéţţîñĝš !!!]"
"Welcome" → "[!!! Ŵéļčöɱé !!!]"
Detta hjälper dig hitta:
- Hardkodade strängar (blir inte omslutna i [!!! !!!])
- Layoutproblem (accenterade tecken är bredare)
- Text som klipps av
Steg 7: Optimera för appbutiker (ASO)
Översätt din appbutikslistning också:
App Store-lokalisering checklista
✅ Appnamn (kan skilja sig åt per locale) ✅ Underrubrik/kort beskrivning ✅ Nyckelord (forska lokala söktermer) ✅ Full beskrivning ✅ Skärmdumpar (använd lokalanpassat UI) ✅ Förhandsvisningsvideo (lägg till undertexter eller voiceover) ✅ Vad är nytt (uppdateringsnoter)
Effekt: Appar med lokalanpassade butikslistningar ser 128 % fler nedladdningar i genomsnitt (App Annie, 2024).
Vanliga lokaliseringfällor
Fälla 1: Kulturell okänslighet
❌ Använda handgester: Tummen upp är stötande i vissa Mellanösternländer ❌ Färgbetydelser: Vitt betyder renhet i västerländska kulturer, död i kinesisk kultur ❌ Symboler: Röd X betyder universellt fel? Nej – rött är tur i Kina
Fälla 2: Ignorera RTL-språk
Appar behöver speglas helt för arabiska/hebreiska:
Engelska (LTR): [←Back] Title [Menu→]
Arabiska (RTL): [→Menu] العنوان [Back←]
iOS: Aktivera RTL-stöd i Interface Builder
Android: Använd start/end istället för left/right i layouter
Webb: Använd CSS logiska egenskaper (margin-inline-start istället för margin-left)
Fälla 3: Konkatenering av strängar
Aldrig bygga meningar genom att konkatenera:
// DÅLIGT - Grammatiken kommer brytas på andra språk
const message = "You have " + count + " messages";
// BRA - Använd kompletta översättbara strängar
const message = t('messages_count', { count });
// "messages_count": "You have {{count}} messages"
Varför? Ordordningen ändras beroende på språk:
- Engelska: "You have 5 messages"
- Japanska: "メッセージが5件あります" (Meddelanden 5 stycken finns)
- Tyska: "Sie haben 5 Nachrichten"
Fälla 4: Ingen planering för textutvidgning
Budgetera extra utrymme:
| Språk | Utvidgning |
|---|---|
| Tyska | +30-40% |
| Franska | +20-30% |
| Spanska | +20-30% |
| Kinesiska | -30% (kortare!) |
Verktyg för app-lokalisering
Översättningshanteringsplattformar
- Lokalise - Populärt för mobilappar
- Crowdin - Bra för open source-projekt
- Phrase - Företagsnivå
- POEditor - Gratis nivå tillgänglig
AI-översättning för lokaliseringfiler
AI Trans - Byggt för utvecklare lokaliseringfiler:
- Identifierar automatiskt .strings, strings.xml, JSON-format
- Bevarar alla platshållare (%@, %d, %1$s, {{var}})
- Bibehåller filstruktur och kommentarer
- Hanterar pluraler korrekt
- Pris: $10 för 1M tecken (Standard) eller $50 för 10M tecken (Business)
Exempelkostnad för typiska appar:
- Liten app (500 strängar, ~50 000 tecken): $0,50 för översättning till 5 språk
- Medelstor app (2 000 strängar, ~200 000 tecken): $2 för 10 språk
- Stor app (10 000 strängar, ~1M tecken): $10 för 15 språk
Arbetsflöde:
1. Ladda upp din en.lproj/Localizable.strings (eller strings.xml, eller i18n JSON)
2. Välj målspråk (spanska, franska, tyska, japanska, etc.)
3. AI bevarar alla %@, %d, {{var}} platshållare automatiskt
4. Ladda ner översatta es.lproj/, fr.lproj/, de.lproj/, ja.lproj/
5. Dra in i Xcode/Android Studio → Klar
jämfört med traditionell översättning:
| Aspekt | AI Trans | Översättningsbyrå |
|---|---|---|
| 2 000 strängar | $2 | $2 000-4 000 |
| Tid | 5 minuter | 2-3 veckor |
| Revideringar | GRATIS | $500+/revidering |
| Platshållarfel | 0% (auto-bevarad) | 5-10% (manuell) |
Mätning av lokaliseringens ROI
Spåra dessa mått:
Användarförvärv:
- Nedladdningar per land/språk
- Kostnad per installation per lokal
- Organisk vs betald uppdelning per region
Engagemang:
- Sessionlängd per språk
- Funktionanvändning per lokal
- Behållningsgrad (Dag 1, 7, 30)
Intäkter:
- In-app-köp per valuta
- Prenumerationskonvertering per land
- LTV (Lifetime Value) per språk
Exempel på ROI-beräkning:
Kostnad för lokalisering: $5 000 (översättning + utvecklingstid)
Ytterligare nedladdningar: +10 000 från nya marknader
Konverteringsgrad: 2% till betalande ($9,99/månad)
Månatlig återkommande intäkt: 200 användare × $9,99 = $1 998
Betaltid: 2,5 månader
Årlig ROI: 379%
Kom igång: Din första lokalisering
Här är en praktisk 2-veckorsplan för att lansera din första lokalisering:
Vecka 1: Förbered din kodbas
Dagarna 1-2: Granska alla hårdkodade strängar Dagarna 3-4: Flytta ut till .strings/strings.xml/JSON Dag 5: Implementera i18n-bibliotek (om webbapp)
Vecka 2: Översätt och testa
Dagarna 1-2: Översätt dina strängar (börja med spanska eller kinesiska—största icke-engelska marknader) Dagarna 3-4: Testa layouter med översatt text Dag 5: Uppdatera App Store-listning på målspråk
Lansering: Skicka till App Store/Play Store med nytt språk
Slutsats
App-lokalisering är en av de mest lönsamma investeringarna du kan göra:
- 🌍 Tillgång till 75% av användarna du missar idag
- 💰 26% genomsnittlig intäktsökning per ny marknad
- ⭐ Bättre betyg (användare älskar appar på sitt språk)
- 🚀 Konkurrensfördel (de flesta appar är inte lokaliserade)
Börja smått: Välj en högvalör-marknad (spanska för USA/LATAM, japanska för Asien, tyska för EU) och lokalisera bara dina kärnanvändarflöden. Du behöver inte översätta varje sträng dag ett.
Det tekniska arbetet är enkelt—flytta ut strängar, använd korrekta formaterings-API:er, testa layouter. Översättningen i sig är den enklaste delen med moderna AI-verktyg.
Redo att gå globalt? Börja översätta dina app-strängar med AI Trans och skicka din första lokalanpassade version denna månad.