Come utilizzare la localizzazione in C #


268

Non riesco proprio a far funzionare la localizzazione.

Ho una biblioteca di classe. Ora voglio creare file resx e restituire alcuni valori basati sulla cultura del thread.

Come lo posso fare?


PS: assicurati di aver installato l'estensione gratuita Microsoft MAT (Multilingual App Toolkit) per visual studio ;-)
juFo

Risposte:


571
  • Aggiungi un file di risorse al tuo progetto (puoi chiamarlo "strings.resx") nel modo seguente:
    Fai clic con il pulsante destro del mouse su Proprietà nel progetto, seleziona Aggiungi -> Nuovo elemento ... nel menu di scelta rapida, quindi nell'elenco di Gli elementi di Visual C # selezionano "File di risorse" e lo denominano strings.resx.
  • Aggiungi una risouce di stringa nel file resx e assegnagli un buon nome (esempio: chiamalo "Hello" con e assegnagli il valore "Hello")
  • Salvare il file di risorse ( nota: questo sarà il file di risorse predefinito , poiché non ha un codice lingua di due lettere)
  • Aggiungi riferimenti al tuo programma: System.ThreadingeSystem.Globalization

Esegui questo codice:

Console.WriteLine(Properties.strings.Hello);

Dovrebbe stampare "Ciao".

Ora, aggiungi un nuovo file di risorse, chiamato "strings.fr.resx" (nota la parte "fr"; questa conterrà risorse in francese). Aggiungi una risorsa stringa con lo stesso nome di strings.resx, ma con il valore in francese (Name = "Hello", Value = "Salut"). Ora, se si esegue il seguente codice, dovrebbe stampare Salut:

Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("fr-FR");
Console.WriteLine(Properties.strings.Hello);

Quello che succede è che il sistema cercherà una risorsa per "fr-FR". Non ne troverà uno (dal momento che abbiamo specificato "fr" nel tuo file "). Tornerà quindi a cercare" fr ", che trova (e usa).

Il seguente codice stamperà "Ciao":

Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("en-US");
Console.WriteLine(Properties.strings.Hello);

Questo perché non trova alcuna risorsa "en-US" e nemmeno nessuna risorsa "en", quindi tornerà al valore predefinito, che è quello che abbiamo aggiunto dall'inizio.

È possibile creare file con risorse più specifiche se necessario (ad esempio strings.fr-FR.resx e strings.fr-CA.resx per il francese rispettivamente in Francia e Canada). In ciascuno di questi file dovrai aggiungere le risorse per quelle stringhe che differiscono dalla risorsa a cui ricorrere. Quindi, se un testo è lo stesso in Francia e Canada, puoi inserirlo in strings.fr.resx, mentre le stringhe che sono diverse nel francese canadese potrebbero andare in strings.fr-CA.resx.


24
La risposta potrebbe fare riferimento al sistema idraulico "dietro le quinte" che viene eseguito da Visual Studio qui: file resx.designer.cs, facendo funzionare l'intellisense; assembly satellite compilati con la libreria di classi, che devono essere distribuiti con l'assembly compilato e eventuali progetti successivi che lo utilizzano, ecc. La risposta è semplice e semplice, ma non aiuta a spiegare dove potrebbero andare le cose, ad es. non usi Visual Studio.
Tao,

13
+1 post! Invece di creare manualmente i file, prova Zeta Resource Editor ( zeta-resource-editor.com/index.html ). È gratuito e ti aiuta a fare questo tipo di traduzioni MOLTO più velocemente che in VS.
Killnine,

4
Access Modifierdeve essere impostato Publicper la generazione della classe di risorse. La classe non è necessariamente nello spazio dei nomi Proprietà, è dove si posiziona il file .resx.
Andrey Moiseev,

3
Tenere presente che in VS 2017 resx con localizzazione in winform non funziona a causa di un bug (almeno fino alla versione 15.4). Un biglietto è disponibile: developercommunity.visualstudio.com/content/problem/63772/…
muccix

4
A partire da .NET 4.5 è anche possibile utilizzare System.Globalization.CultureInfo.DefaultThreadCurrentCulture anziché Thread.CurrentThread.CurrentUICulture in modo da modificare le impostazioni internazionali per l'intera applicazione anziché thread per thread
GrixM

41

È abbastanza semplice, in realtà. Creare un nuovo file di risorse, ad esempio Strings.resx. Imposta Access Modifiersu Public. Utilizzare il modello di file appropriato, quindi Visual Studio genererà automaticamente una classe accessor (il nome sarà Strings, in questo caso). Questa è la tua lingua predefinita.

Ora, quando si desidera aggiungere, ad esempio, la localizzazione tedesca, aggiungere un file resx localizzato. Questo sarà in genere Strings.de.resxin questo caso. Se vuoi aggiungere ulteriore localizzazione per, diciamo, per l'Austria, creerai anche un Strings.de-AT.resx.

Ora vai a creare una stringa - diciamo una stringa con il nome HelloWorld. Nel tuo Strings.resx, aggiungi questa stringa con il valore "Ciao, mondo!". In Strings.de.resx, aggiungi "Hallo, Welt!". E in Strings.de-AT.resx, aggiungi "Servus, Welt!". Fin qui.

Ora hai questa Stringsclasse generata e ha una proprietà con un getter HelloWorld. Ottenere questa proprietà caricherà "Servus, Welt!" quando la tua locale è de-AT, "Ciao, Welt! quando la tua locale è qualsiasi altra de locale (compresi de-DE e de-CH) e" Ciao, Mondo! "quando la tua locale è qualcos'altro. Se una stringa è mancante nella versione localizzata, il gestore delle risorse camminerà automaticamente lungo la catena, dalla risorsa più specializzata a quella invariante.

Puoi usare la ResourceManagerclasse per un maggiore controllo su come stai caricando esattamente le cose. Anche la Stringsclasse generata la usa.


come impostare le impostazioni internazionali?
Matheus Simon,

1
@MatheusSimon: Non è necessario. Per impostazione predefinita, viene utilizzata la locale corrente dell'utente. Se si desidera forzare una determinata locale (ad esempio per consentire agli utenti di cambiare manualmente la lingua), è necessario impostare System.Threading.Thread.CurrentCulture e CurrentUICulture in ciascun thread , probabilmente prima che vengano caricate le risorse per la prima volta. È più facile riavviare un'applicazione per questo piuttosto che aggiornarlo in fase di esecuzione.
OregonGhost,

15

Inoltre, l'ottima risposta di @Fredrik Mörk sulle stringhe, per aggiungere la localizzazione a un modulo , procedi come segue:

  • Impostare la proprietà del modulo"Localizable" sutrue
  • Modifica la Languageproprietà del modulo nella lingua desiderata (da un bel menu a discesa con tutti in)
  • Traduci i controlli in quella forma e spostali se necessario (schiaccia quelle frasi francesi davvero lunghe!)

Modifica: questo articolo di MSDN sulla localizzazione di Windows Form non è quello originale che ho collegato ... ma potrebbe fare luce se necessario. (il vecchio è stato portato via)


L'articolo msdn non è più disponibile, qualche rimpiazzo?
fuomag9,

Non sono sicuro - ho collegato il migliore che potessi vedere, ma non ricordo com'era l'articolo 7 anni fa;)
noelicus,

14

Ottima risposta di F.Mörk. Ma se vuoi aggiornare la traduzione o aggiungere nuove lingue una volta rilasciata l'applicazione, sei bloccato, perché devi sempre ricompilarlo per generare il file resources.dll.

Ecco una soluzione per compilare manualmente una dll di risorse. Utilizza gli strumenti resgen.exe e al.exe (installati con sdk).

Supponi di avere un file di risorse Strings.fr.resx, puoi compilare una DLL di risorse con il seguente batch:

resgen.exe /compile Strings.fr.resx,WpfRibbonApplication1.Strings.fr.resources 
Al.exe /t:lib /embed:WpfRibbonApplication1.Strings.fr.resources /culture:"fr" /out:"WpfRibbonApplication1.resources.dll"
del WpfRibbonApplication1.Strings.fr.resources
pause

Assicurati di mantenere lo spazio dei nomi originale nei nomi dei file (qui "WpfRibbonApplication1")


2
Grazie per il commento su come preservare lo spazio dei nomi (y), che - se perso - non genererà alcun errore, ma semplicemente tornerà alla risorsa di fallback.
Mosca Pt,

11

Una correzione ed elaborazione della risposta di @Fredrik Mörk .

  • Aggiungi un strings.resxfile di risorse al tuo progetto (o un nome file diverso)
  • Impostare Access Modifiersu Public(nella strings.resxscheda del file aperto )
  • Aggiungi una nuova risorsa stringa nel file resx: (esempio: nome Hello, valore Hello)
  • Salva il file di risorse

Visual Studio genera automaticamente una rispettiva stringsclasse, che viene effettivamente inserita strings.Designer.cs. La classe si trova nello stesso spazio dei nomi in cui ti aspetteresti di inserire un .csfile appena creato .

Questo codice viene sempre stampato Hello, poiché si tratta della risorsa predefinita e non sono disponibili risorse specifiche della lingua:

Console.WriteLine(strings.Hello);

Ora aggiungi una nuova risorsa specifica per la lingua:

  • Aggiungi strings.fr.resx(per il francese)
  • Aggiungi una stringa con lo stesso nome di prima, ma con un valore diverso: (nome Hello, valore Salut)

Viene stampato il seguente codice Salut:

Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("fr-FR");
Console.WriteLine(strings.Hello);

Da quale risorsa viene utilizzata dipende Thread.CurrentThread.CurrentUICulture. È impostato in base all'impostazione della lingua dell'interfaccia utente di Windows o può essere impostato manualmente come in questo esempio. Ulteriori informazioni su questo qui .

Puoi aggiungere risorse specifiche per Paese come strings.fr-FR.resxo strings.fr-CA.resx.

La stringa da utilizzare è determinata in questo ordine di priorità:

  • Da risorse specifiche del paese come strings.fr-CA.resx
  • Da risorse specifiche della lingua come strings.fr.resx
  • Di default strings.resx

Si noti che le risorse specifiche della lingua generano assemblee satellitari .

Scopri anche come CurrentCulturedifferisce da CurrentUICulture qui .


1

Nel mio caso

[assembly: System.Resources.NeutralResourcesLanguage("ru-RU")]

in AssemblyInfo.cs ha impedito che le cose funzionassero normalmente.


0

Oltre alla risposta @Eric Bole-Feysot :

Grazie agli assemblaggi satellitari, la localizzazione può essere creata sulla base di file .dll / .exe . Per di qua:

  • il codice sorgente (progetto VS) potrebbe essere separato dal progetto linguistico,
  • l'aggiunta di una nuova lingua non richiede la ricompilazione del progetto,
  • la traduzione potrebbe essere effettuata anche dall'utente finale.

Esiste uno strumento poco noto chiamato LSACreator (gratuito per uso non commerciale o opzione di acquisto) che consente di creare la localizzazione in base ai file .dll / .exe. Infatti, internamente (nella directory dei progetti linguistici) crea / gestisce versioni localizzate di file resx e compila un assembly in modo simile a quanto descritto da @Eric Bole-Feysot .


0

ResourceManager e .resx sono un po 'disordinati.

È possibile utilizzare Lexical.Localization ¹ che consente di incorporare nel codice valori predefiniti e valori specifici della cultura e di essere espansi in file di localizzazione esterni per altre culture (come .json o .resx).

public class MyClass
{
    /// <summary>
    /// Localization root for this class.
    /// </summary>
    static ILine localization = LineRoot.Global.Type<MyClass>();

    /// <summary>
    /// Localization key "Ok" with a default string, and couple of inlined strings for two cultures.
    /// </summary>
    static ILine ok = localization.Key("Success")
            .Text("Success")
            .fi("Onnistui")
            .sv("Det funkar");

    /// <summary>
    /// Localization key "Error" with a default string, and couple of inlined ones for two cultures.
    /// </summary>
    static ILine error = localization.Key("Error")
            .Format("Error (Code=0x{0:X8})")
            .fi("Virhe (Koodi=0x{0:X8})")
            .sv("Sönder (Kod=0x{0:X8})");

    public void DoOk()
    {
        Console.WriteLine( ok );
    }

    public void DoError()
    {
        Console.WriteLine( error.Value(0x100) );
    }
}

¹ (Sono il manutentore di quella biblioteca)


0

In generale metti le tue traduzioni in file di risorse, ad esempio risorse.resx.

Ogni cultura specifica ha un nome diverso, ad esempio risorse.nl.resx, risorse.fr.resx, risorse.de.resx, ...

Ora la parte più importante di una soluzione è mantenere le tue traduzioni. In Visual Studio installa lo strumento Microsoft MAT: Multilingual App Toolkit (MAT). Funziona con winforms, wpf, asp.net (core), uwp, ...

In generale, ad esempio per una soluzione WPF, nel progetto WPF

  • Installa l'estensione Microsoft MAT per Visual Studio.
  • In Esplora soluzioni, accedere a Progetto> Proprietà> AssemblyInfo.cs
  • Aggiungi in AssemblyInfo.cs la tua lingua predefinita, neutrale (nel mio caso inglese): [assembly: System.Resources.NeutralResourcesLanguage("en")]
  • Seleziona il tuo progetto in Esplora soluzioni e in Visual Studio, dal menu in alto, fai clic su "Strumenti"> "Multilingual App Toolkit"> "Abilita selezione" per abilitare MAT per il progetto.
    • Ora fai clic destro sul progetto in Esplora soluzioni, seleziona "Multilingual App Toolkit"> "Aggiungi lingue di traduzione ..." e seleziona la lingua per la quale desideri aggiungere traduzioni. ad esempio olandese.

Quello che vedrai è che verrà creata una nuova cartella, chiamata "MultilingualResources" contenente un ....nl.xlffile.

L'unica cosa che ora devi fare è:

  1. aggiungi la tua traduzione al tuo file resources.resx predefinito (nel mio caso inglese)
  2. Traduci facendo clic sul file .xlf (NON sul file .resx) poiché i file .xlf genereranno / aggiorneranno i file .resx.

(i file .xlf dovrebbero aprirsi con "Editor multilingue", in caso contrario, fare clic con il tasto destro del mouse sul file .xlf, selezionare "Apri con ..." e selezionare "Editor multilingue".

Divertiti! ora puoi anche vedere ciò che non è stato tradotto, esportare traduzioni in xlf verso società di traduzione esterne, importarle di nuovo, riciclare traduzioni da altri progetti ecc ...

Ulteriori informazioni:

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.