Strategie efficaci per la localizzazione in .NET [chiuso]


121

Sto sviluppando l'interfaccia utente per un'applicazione .NET MVC che richiederà la localizzazione internazionale di tutti i contenuti nel prossimo futuro. Conosco molto bene .NET in generale, ma non ho mai avuto un progetto che richiedesse un'attenzione così significativa sull'accessibilità internazionale.

Il progetto è inizialmente in inglese. Quali misure devo prendere a questo punto per rendere più semplice l'implementazione della localizzazione in futuro?


2
Ottima domanda! Sto affrontando una situazione simile e mi piacerebbe vedere gli esperti pesare su questo.

Qualcuno ha buoni standard per la gestione delle risorse? Il valore localizzato potrebbe includere anche immagini e non solo stringhe.

1
È un'interfaccia utente WPF / silverlight o Winforms? Dalla mia (limitata) esperienza, l'esperienza WinForms per la localizzazione è molto più semplice di WPF / Silverlight.
Pete Stensønes,

1
Se si finisce per immagazzinare le stringhe localizzate nel database, invece di file di risorse, si consiglia di dare un'occhiata a questa discussione: stackoverflow.com/questions/2458615/...

1
@Pete, @smartcaveman ha detto che "sta sviluppando l'interfaccia utente per un'applicazione .NET MVC", quindi ...
BrunoSalvino,

Risposte:


74

Stai sviluppando l'applicazione ASP.Net MVC, vero? Altre risposte sembrano essere specifiche per le applicazioni desktop. Fammi catturare cose comuni:

Rilevazione delle impostazioni locali

È abbastanza importante che l'applicazione rilevi correttamente le impostazioni internazionali dell'utente. Nell'applicazione desktop, CultureInfo.CurrentCulture contiene le impostazioni internazionali di formattazione preferite (quella che dovrebbe essere utilizzata per formattare numeri, date, valute, ecc.) Mentre CultureInfo.CurrentUICulture contiene le impostazioni internazionali preferite dell'interfaccia utente (quella che dovrebbe essere utilizzata per visualizzare i messaggi localizzati) . Per le applicazioni Web, è necessario impostare entrambe le culture su auto (per rilevare automaticamente le impostazioni locali dall'intestazione AcceptLanguage) a meno che non si desideri implementare un flusso di lavoro di rilevamento delle impostazioni locali sofisticato (ad esempio, si desidera supportare il cambio della lingua su richiesta).

Esternalizzare le stringhe

Tutte le stringhe dovrebbero provenire da risorse, ovvero file Resx. Nell'app Winforms è facilmente raggiungibile impostando la proprietà Localizable su true. Dovresti anche esternalizzare (purtroppo) manualmente le stringhe che provengono dai tuoi modelli. È anche relativamente semplice. In Asp.Net dovresti esternalizzare tutto manualmente ...

layout

Devi assolutamente consentire l'espansione della stringa. Nel mondo Winforms è realizzabile tramite TableLayoutPanel che dovrebbe essere usato per assicurarsi che il layout si adatterà automaticamente per adattarsi al testo più lungo. Nel mondo web, sei un po 'sfortunato. Potrebbe essere necessario implementare il meccanismo di localizzazione CSS - un modo per modificare (sovrascrivere) le definizioni CSS. Ciò consentirebbe alle persone di localizzazione di modificare i problemi di stile su richiesta. Assicurati che ogni elemento HTML nella pagina renderizzata abbia un ID univoco, che consentirà di indirizzarlo con precisione.

Questioni specifiche per la cultura

Evita l'uso di grafica, colori e suoni che potrebbero essere specifici per la cultura occidentale. Se ne hai davvero bisogno, ti preghiamo di fornire mezzi di localizzazione. Evita la grafica sensibile alla direzione (poiché questo sarebbe un problema quando provi a localizzarlo per dire arabo o ebraico). Inoltre, non dare per scontato che il mondo intero stia usando gli stessi numeri (cioè non è vero per l'arabo).

ToString () e Parse ()

Assicurati di passare sempre CultureInfo quando chiami ToString () a meno che non sia supportato. In questo modo stai commentando le tue intenzioni. Ad esempio: se si utilizza un numero internamente e per qualche motivo è necessario convertirlo in stringa utilizzare:

int i = 42;
var s = i.ToString(CultureInfo.InvariantCulture);

Per i numeri che verranno visualizzati per l'uso dell'utente:

var s = i.ToString(CultureInfo.CurrentCulture); // formatting culture used

Lo stesso vale per Parse (), TryParse () e persino ParseExact () - alcuni brutti bug potrebbero essere introdotti senza l'uso corretto di CultureInfo. Questo perché una povera anima di Microsoft, piena di buone intenzioni, ha deciso che è una buona idea trattare CultureInfo.CurrentCulture come predefinito (sarebbe usato se non si passa nulla), dopo tutto quando qualcuno sta usando ToString ( ) lui / lei vuole mostrarlo all'utente, giusto? Scoprire che non è sempre il caso, ad esempio provare a memorizzare il numero di versione dell'applicazione nel database e quindi convertirlo in istanza della classe Version. In bocca al lupo.

Date e fusi orari

Assicurarsi di archiviare e creare sempre un'istanza di DateTime in UTC (utilizzare DateTime.UtcNow anziché DateTime.Now). Converti l'ora locale in formato locale dopo aver visualizzato:

DateTime now = DateTime.UtcNow;
var s = now.ToLocalTime().ToString(CultureInfo.CurrentCulture);

Se devi inviare e-mail con riferimento temporale nel corpo, assicurati di includere le informazioni sul fuso orario - includi sia l'offset UTC sia l'elenco delle città:

DateTime someDate; // i.e. from database
var formattedDate = String.Format("{0} {1}", 
             someDate.ToLocaleTime().ToString(CultureInfo.CurrentCulture),
             TimeZoneInfo.Local.DisplayName);

Messaggi composti

Sei già stato avvisato di non concatenare le stringhe. Invece probabilmente useresti String.Format () come mostrato sopra. Tuttavia, devo dichiarare che è necessario ridurre al minimo l'uso di messaggi composti. Questo perché le regole grammaticali di destinazione sono abbastanza diverse, quindi i traduttori potrebbero non solo riordinare la frase (questo sarebbe risolto usando segnaposto e String.Format ()), ma tradurre l'intera frase in modo diverso in base a cosa sarà sostituito. Lascia che ti dia alcuni esempi:

// Multiple plural forms
English: 4 viruses found.
Polish: Znaleziono 4 wirusy. **OR** Znaleziono 5 wirusów.

// Conjugation
English: Program encountered incorrect character | Application encountered incorrect character.
Polish: Program napotkał nieznaną literę | Aplikacja napotkała nieznaną literę.

Altre questioni di concatenazione

La concatenazione non è limitata alle stringhe. Evita di disporre i controlli insieme, ad esempio:

Ricordamelo di nuovo tra [casella di testo con numero] giorni.

Questo dovrebbe essere riprogettato in modo simile a: Ricordamelo di nuovo in questo numero di giorni: [casella di testo].

Codifica dei caratteri e caratteri

Salvare sempre, trasferire, qualunque testo in Unicode (cioè in UTF-8). Non scrivere i caratteri nel codice: potrebbe essere necessario modificarli nella localizzazione e questo disattiverà il meccanismo di fallback dei caratteri predefinito (nel caso di Winforms). Ricorda di consentire caratteri "strani" nella maggior parte dei campi (ad es. Nome utente).

Test

Probabilmente dovrai implementare la cosiddetta pseudo traduzione, ovvero creare risorse per dire cultura tedesca e copiare le tue stringhe inglesi aggiungendo prefisso e suffisso. Puoi anche avvolgere i segnaposto per rilevare facilmente stringhe composte. Lo scopo della pseudo traduzione è di rilevare problemi di localizzazione come stringhe codificate, problemi di layout e uso eccessivo di messaggi composti.


5
Per quanto riguarda i messaggi composti : una volta ho dovuto fare più forme plurali. Ho esteso in String.Formatmodo che potesse supportare questa sintassi interessante: "There {0:was|were} {0} {0:virus|viruses} found."ogni lingua può caricare le proprie regole, in modo da poter fare "Znaleziono {0} {0:wirusy|wirusów}." La fonte è su GitHub: github.com/scottrippey/SmartFormat/wiki
Scott Rippey

2
@Scott Rippey Hai notato che l'esempio polacco recita "Znaleziono 4 wirusy. O Znaleziono 5 wirusów." <- Il polacco, come molte altre lingue, ha più di due forme plurali e anche le regole per distinguerle possono essere complesse. Qui devo lasciare il polacco poiché non lo parlo, ma nella mia lingua, la forma plurale per 101 cose è la stessa di quella per 1 cosa. Potresti dare un'occhiata a come GNU gettext affronta questo problema: gnu.org/s/hello/manual/gettext/Plural-forms.html
gregopet

2
@gregopet Il mio esempio polacco è stato inventato, perché non lo parlo, ma è esattamente quello che fa il progetto SmartFormat. Ecco un esempio migliore: "{0} {0:plik|pliki|plików}". Il formattatore ha una regola polacca che determina quale delle 3 forme utilizzare e determina correttamente i casi speciali. Attualmente sto lavorando per aggiungere altre regole, quindi l' gettextarticolo si rivelerà molto utile, grazie.
Scott Rippey,

Per la pseudo-localizzazione, ho creato uno strumento di pseudolocalizzazione online gratuito su pseudolocalize.com
JerSchneid,

74

Alcune cose di base che dovresti prendere in considerazione:

Esternalizzare tutte le risorse di stringa

Tutte le risorse devono essere contenute in file esterni che possono essere distribuiti per la localizzazione. Non dimenticare i messaggi di errore, se vuoi anche questi localizzati.

Consentire spazio sufficiente per l'espansione della stringa

Le stringhe in alcune lingue tendono ad essere fino al 30% più lunghe (come il greco), ad esempio, quindi assicurati di progettare la tua interfaccia utente in modo tale che le stringhe possano espandersi se necessario. Ecco un esempio piuttosto estremo per il francese:

Ok -> Acceptre (francese - Espansione del 400%)

Consiglierei di fare una sorta di pseudo traduzione come punto di partenza ( http://en.wikipedia.org/wiki/Pseudolocalization ). Oppure potresti tradurre le tue risorse tramite Google Translate o Bing. Questo ti darà una buona indicazione di come appariranno le traduzioni effettive.

Fai attenzione al testo nelle immagini

Se usi delle immagini nella tua applicazione, assicurati che non contengano alcun testo, questo ovviamente non può essere tradotto.

Non codificare mai alcun percorso per le cartelle di Windows

Ovvio, ma l'ho visto in passato. Ad esempio, C:\Program Filesè tradotto su alcune versioni internazionali di Windows, ad esempio C:\Programmesu un sistema operativo tedesco.

Evita di usare termini specifici della locale

Ad esempio, se chiedi a qualcuno la sua "scuola superiore" su un modulo, questo ha poco significato nell'Europa occidentale.

Evitare di creare stringhe tramite concatenazione di stringhe

Ad esempio, questo sembra innocuo:

strWelcome = ReadExternalString("Welcome"); 
strMessage = strWelcome + ", " + UserName;

Ma l'ordine delle parole in giapponese, ad esempio, sarebbe diverso, quindi potrebbe non avere alcun senso.

Impostazioni data / ora

Assicurati sempre di ottenere il formato data / ora dal sistema operativo.


@Jimmy C, come si fa a costruire stringhe per coerenza logica indipendente dalla lingua?
smartcaveman,

14
@Smart fa qualcosa nella tua risorsa come "{0}, {1}" quindi quando lo localizzi, usa string.format e passa il saluto e il nome utente. Inoltre, questo ti dà il vantaggio di avere "La velocità {0} corrente è {1} {2}" e puoi passare in "Motore", "50" e "MPH" e, quando traduci la tua frase, puoi spostare { 0} ecc. Intorno a dove hanno senso in quella lingua
taylonr

4
Buona lista JimmyC. "Non codificare mai alcun percorso per le cartelle di Windows" mi ha ricordato "Usa sempre Path.Combine" invece della concatenazione di stringhe per i percorsi di Windows.

@ Jimmy-C Ottima risposta!

1
Environment.GetFolderPath può essere utilizzato per ottenere percorsi validi per percorsi comuni come Documenti senza dipendere dal nome inglese per tali cartelle.
Crippledsmurf

24

Considerazioni speciali per le lingue asiatiche

Oltre a tutte le ottime risposte già qui, alcuni attenti alle lingue asiatiche:

Attenzione alle diverse lunghezze di testo

Il testo cinese e coreano tende ad essere molto più breve dell'equivalente testo inglese (dal momento che di solito hai bisogno di meno caratteri in blocco per scrivere la stessa cosa), quindi una pagina potrebbe effettivamente apparire vuota in cinese ma inceppata in tedesco ... Devi fare un po 'di dimensionamento dinamico qui per apparire bene.

Tuttavia, il testo giapponese di solito tende ad essere molto più lungo, anche più lungo del testo inglese equivalente in termini di conteggio dei caratteri.

Fai attenzione al layout della linea di base e all'aspetto "scorrevole"

I caratteri asiatici sono di solito disposti sulla linea di base , che non include i discendenti (cioè la parte inferiore di y, g, q, j ecc.) Quando si formatta un elemento dello schermo - di solito pulsanti - con il testo all'interno, e se quello il testo è solo lingue asiatiche (cioè non alfabeti occidentali), quindi il testo sembrerà spostato verso l'alto.

Formattazione di numeri e unità numeriche localizzate

Gestire la formattazione dei numeri in modo diverso. Diversi paesi asiatici hanno modi diversi di formattare i numeri. Lo stesso vale per le valute. Ad esempio, nell'Asia orientale, 10.000 (calante) è un'unità comune. In India, 100.000 (lakh) sono comuni.

Valute locali

Le valute di alcuni paesi hanno molti zeri e nessun punto decimale (ad esempio Giappone, Indonesia, Italia), mentre altri hanno fino a due cifre dopo il punto decimale.

Attenzione ai diversi ordini di parole

L'ordine delle parole potrebbe non essere sempre lo stesso. È preferibile utilizzare {0}, {1} ecc. Nella formattazione della stringa anziché nell'ordine delle parole con codifica rigida se la stringa proviene da una combinazione di diversi pezzi di dati.

Usa l'ordinamento specifico per la locale

L'ordinamento è diverso per lingua e per locale - devi sempre fare affidamento sull'ordinamento specifico delle impostazioni locali di O / S.

Sii molto cauto con i caratteri a larghezza intera / mezza larghezza

Fai attenzione alle differenze tra i caratteri "a larghezza intera" e "a metà larghezza". Le parentesi quadre, la punteggiatura ecc. Possono avere versioni "a larghezza intera" diverse dalle ASCII standard. Se esegui una ricerca o una suddivisione delle stringhe in base a queste lettere, dovrai prima convertire tutti i simboli a larghezza intera in equivalenti a metà larghezza.

Un punto non è un punto ... una virgola non è una virgola ...

Attenzione ai dati di input gotcha - ad esempio, in cinese, un punto non è un punto ".". Una virgola è a larghezza intera, non ",". Non tentare di cercare la punteggiatura occidentale se l'utente che sta inserendo i dati può attivare accidentalmente l'IME in lingua asiatica.

Numeri di telefono

Non dare per scontato nulla nella formattazione del numero di telefono. Non esiste sempre un prefisso ecc. E può essere formattato in modo diverso. Di solito, hanno una stringa di formato per paese.

Non assumere la gente hanno solo un numero di cellulare, o un numero di fax, ecc Non è in questo modo in Asia.

Indirizzi: più densi di quanto si pensi

Per gli indirizzi, non assumere nulla . Potrebbe non essere sempre presente un codice postale. I codici postali potrebbero non essere sempre numeri. Un paese potrebbe non avere province / stati. Un paese può essere solo una grande città (ad esempio Singapore). Per alcuni paesi asiatici, l'unità più piccola di una casa può essere "Sala X, Unità Y, Sezione Z, Piano A, Blocco B, Gruppo C, Proprietà D". In generale, sii molto liberale nel numero di campi e nel numero di caratteri consentiti negli indirizzi.

saluti

I saluti non sono limitati solo a Mr., Mrs. ecc. Anche se probabilmente sei al sicuro usando "M" e "F" per il sesso - non siamo ancora così strani ...


1
L'ultimo paragrafo mi ha fatto sorridere.
BoltClock

Oh, noi (i18n ragazzi) non abbiamo nemmeno ancora iniziato ... Siamo riusciti solo a grattare la superficie :) Se dovessimo parlare di problemi specifici come il supporto GB18030, il nostro post sarebbe troppo lungo per essere gestito da SO :) Grazie per la tua nota comunque, mi mancavano parecchi articoli.
Paweł Dyda,

Circa l'ultimo, credo che il Regno Unito ora accetti ufficialmente "Altro" come sesso. Pensa ai transgender.
Bart Friederichs,

11

Alcuni passaggi di base sono assicurarsi che qualsiasi stringa visualizzata sullo schermo non sia letterale nel codice. Se stai facendo Winforms ogni modulo avrà una risorsa UI. Per finestre di dialogo, report, ecc., Assicurarsi di utilizzare i file di risorse del progetto.

Quindi, invece di "Caricamento non riuscito" nel tuo codice, potresti avere qualcosa come Resources.UploadFailed

In questo modo puoi creare un nuovo file di risorse per ogni lingua che usi (e .Net ti aiuterà in questo.) E avere la stringa localizzata in ogni file.

EDIT Ho dimenticato di menzionare quando stai eseguendo l'interfaccia utente, assicurati di non stipare solo le cose lì dentro. A seconda delle lingue in cui ti stai localizzando, gli immobili potrebbero essere un problema. Ho lavorato a un progetto che aveva il tedesco e il portoghese come i 2 maggiori trasgressori per la crescita delle stringhe. Se non fossimo attenti a stringhe che andavano bene in inglese, francese e italiano sarebbero esplose in tedesco.


1
Dalla mia esperienza con L10n, il russo è lo scenario peggiore. Comunque in Winforms con l'utente corretto di TableLayoutPanels si può gestire con garbo la crescita delle stringhe.
Paweł Dyda,

Sì, la mia esperienza è stata limitata a 7 lingue: inglese, tedesco, portoghese, italiano, francese, spagnolo e giapponese. Ma posso vedere il russo essere cattivo in quanto tendono ad avere molti suffissi e prefissi
taylonr

9

Ti suggerisco di eseguire FXCop o Visual Studio Code Analysis (sono quasi uguali) sui tuoi assembly.

Sono bravi a rilevare il codice .NET che non utilizza i sovraccarichi orientati alla cultura appropriati, come questo: CA1305: specificare IFormatProvider .

Devo aggiungere che questi strumenti sono anche frustranti perché di solito rilevano miliardi di problemi nel tuo codice, ma comunque, anche se non segui ogni regola, dovresti imparare molto.


È questo il valore predefinito o devo specificare alcune impostazioni per cercare regole specifiche della globalizzazione?
smartcaveman,

@smartcaveman - è l'impostazione predefinita (hmm .. in realtà, alcune persone pensano che ci siano molte regole predefinite in questi strumenti :-)
Simon Mourier,

7

Oltre allo specifico come caricare le risorse, mi assicurerei di provare con una versione pseudo-localizzata per cominciare. In caso contrario, è probabile che non si notino i luoghi in cui le considerazioni di internazionalizzazione sono state omesse fino alla fine.


Per un modo rapido e semplice di pseudolocalizzare, ho creato uno strumento online gratuito su pseudolocalize.com
JerSchneid,

6

Oltre a tutti gli altri suggerimenti utili, eccone alcuni mancanti:

Tieni presente che alcuni paesi utilizzano più di una lingua. Ad esempio, in Canada, un utente si aspetterebbe di passare facilmente dall'inglese al francese.

Se fai una domanda all'utente che si aspetta una sola lettera, non aspettarti che l'utente prema il tasto 'Y' per dire Sì.

Prestare molta attenzione nei proc memorizzati che le date nel database SQL sono in formato USA

Il posizionamento di stringhe di testo nel DB consente di aggiungere successivamente lingue aggiuntive senza ridistribuire.

Quando si inviano file di testo scritti per la traduzione, includere sempre una descrizione del contesto per assicurarsi che il traduttore selezioni la parola corretta. Ad esempio, senza contesto, è possibile tradurre "pitch:" in qualcosa a che fare con il suono o in un luogo in cui si gioca a calcio

Le etichette degli indirizzi devono sempre essere convertite. Provincia in Canada, Stato in America, Contea nel Regno Unito


5

Devi considerare:

  1. Routing per multilingua

  2. Sposta tutte le stringhe hardcode nel file di risorse

Un esempio per una proprietà:

Modello:

[Display(Name = <Resource for display name>.<field for this property>)]
[Required(ErrorMessage = <Resource for error message>.<field for this validate message>)]
public string TestProperty { get; set; }

Visualizza:

@Html.LabelFor(m=>m.TestProperty)
@Html.EditorFor(m => m.TestProperty)
@Html.ValidationMessageFor(m => m.TestProperty)

5

Ecco qualcosa non menzionato nel resto delle risposte.

A seconda della complessità dell'applicazione e della sua localizzazione, consiglio vivamente di implementare un fornitore di risorse alternativo e di conservare le risorse localizzate in un database. Con lo schema di localizzazione ASP.NET predefinito, tutte le risorse vengono mantenute nei file RESX, che:

  1. Sono una seccatura nel culo da modificare in Visual Studio
  2. Limitare la distribuzione e la gestione delle risorse localizzate dopo che l'applicazione è stata compilata / spedita / eseguita.

Come possibile caso d'uso, considera la possibilità di fornire language pack per la tua applicazione e la possibilità di importare ed esportare lingue attraverso l'interfaccia utente. I file RESX non sarebbero d'aiuto qui.

In scenari come questo, un fornitore di risorse alternative è molto utile. Maggiori informazioni su come implementarne uno sono disponibili qui . Naturalmente questo è un caso raro più comunemente visto nelle applicazioni aziendali, ma ancora valido.


1
Grazie per aver dedicato del tempo a dare un'occhiata a queste fantastiche risposte e continuare a contribuire con qualcosa di nuovo e utile.
smartcaveman,

+1; Ho creato una vasta applicazione Web in Asp.NET e abbiamo finito per fare traduzioni tramite il database. Spesso venivano aggiunte nuove funzionalità, ma poiché i nostri traduttori non erano esperti nella particolare terminologia utilizzata, siamo stati in grado di rispondere rapidamente alle e-mail di clienti arrabbiati del tipo "Perché stai usando la parola Y per X che è chiaramente sbagliata?".
Gregreget,

3

La cosa più importante è gestire il contenuto in varie lingue. Ho sviluppato personalmente un paio di siti Web e gestire il contenuto in varie lingue è la sfida più grande.

Sto usando Database per archiviare le risorse / i contenuti. Mi dà la flessibilità di aggiungere qualsiasi supporto linguistico che desidero. Ho implementato la logica di ricadere nella lingua inglese se non viene trovata una risorsa in una lingua particolare.

Successivamente puoi utilizzare un traduttore per convertire il valore inglese in qualsiasi lingua.


2

Sintesi delle cose da considerare nell'internazionalizzazione:

  • Tutte le informazioni dovrebbero essere internazionalizzate. Prendi in considerazione che la grafica potrebbe contenere informazioni che vogliamo internazionalizzare.

  • La dimensione dei campi o delle stringhe, a seconda della lingua perché può causarci un problema.

  • L'ordine delle parole dipende dalla lingua che siamo, quindi un ordine in una lingua sarà lo stesso in un'altra.

  • Dobbiamo tener conto del fatto che il formato della data cambierà da una lingua all'altra


1

Fai il test della Turchia :

L'internazionalizzazione del software è difficile nelle migliori circostanze , ma mi ha sempre stupito la frequenza con cui un particolare paese si è presentato nelle discussioni sui problemi di internazionalizzazione: la Turchia ...

Se ti interessa un po 'di localizzazione o internazionalizzazione, imponi che il tuo codice venga eseguito nelle impostazioni locali turche non appena ragionevolmente possibile . È un segnale forte per il tuo codice in esecuzione nella maggior parte - ma non in tutti - culture e locali ...

Se il tuo sito / programma funziona bene con un client turco, puoi essere sicuro che funzionerà sulla maggior parte delle altre piattaforme.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.