Eu simplesmente não consigo fazer a localização funcionar.
Eu tenho uma biblioteca de classes. Agora eu quero criar arquivos resx lá e retornar alguns valores com base na cultura do thread.
Como eu posso fazer isso?
Eu simplesmente não consigo fazer a localização funcionar.
Eu tenho uma biblioteca de classes. Agora eu quero criar arquivos resx lá e retornar alguns valores com base na cultura do thread.
Como eu posso fazer isso?
Respostas:
strings.resx
.System.Threading
eSystem.Globalization
Execute este código:
Console.WriteLine(Properties.strings.Hello);
Ele deve imprimir "Olá".
Agora, adicione um novo arquivo de recurso chamado "strings.fr.resx" (observe a parte "fr"; esta conterá recursos em francês). Adicione um recurso de sequência com o mesmo nome que em strings.resx, mas com o valor em francês (Name = "Hello", Value = "Salut"). Agora, se você executar o seguinte código, ele deverá imprimir Salut:
Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("fr-FR");
Console.WriteLine(Properties.strings.Hello);
O que acontece é que o sistema procurará um recurso para "fr-FR". Ele não encontrará um (já que especificamos "fr" em seu arquivo "). Em seguida, retornará à verificação de" fr ", que encontra (e usa).
O código a seguir imprimirá "Hello":
Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("en-US");
Console.WriteLine(Properties.strings.Hello);
Isso ocorre porque ele não encontra nenhum recurso "en-US" e também nenhum recurso "en"; portanto, ele volta ao padrão, que foi o que adicionamos desde o início.
Você pode criar arquivos com recursos mais específicos, se necessário (por exemplo, strings.fr-FR.resx e strings.fr-CA.resx para francês na França e no Canadá, respectivamente). Em cada um desses arquivos, você precisará adicionar os recursos para as cadeias que diferem do recurso para o qual ele retornaria. Portanto, se um texto é o mesmo na França e no Canadá, você pode colocá-lo em strings.fr.resx, enquanto as strings diferentes no francês canadense podem ir para strings.fr-CA.resx.
Access Modifier
deve ser definido Public
para que a classe de recurso seja gerada. A classe não é necessária no espaço de nomes Propriedades, é onde você coloca o arquivo .resx.
É bem simples, na verdade. Crie um novo arquivo de recurso, por exemplo Strings.resx
. Defina Access Modifier
como Public
. Use o modelo de arquivo apropriado, para que o Visual Studio gere automaticamente uma classe de acessador (o nome será Strings
, nesse caso). Este é o seu idioma padrão.
Agora, quando você quiser adicionar, por exemplo, localização alemã, adicione um arquivo resx localizado. Isso será tipicamente Strings.de.resx
neste caso. Se você deseja adicionar localização adicional para, digamos, na Áustria, criará adicionalmente um Strings.de-AT.resx
.
Agora vá criar uma string - digamos uma string com o nome HelloWorld
. No seu Strings.resx
, adicione essa sequência com o valor "Olá, mundo!". Em Strings.de.resx
, adicione "Olá, Welt!". E em Strings.de-AT.resx
, adicione "Servus, Welt!". Até agora.
Agora você tem essa Strings
classe gerada e ela possui uma propriedade com um getter HelloWorld
. Obter esta propriedade carregará "Servus, Welt!" quando seu código de idioma estiver desativado, "Olá, Welt! quando seu código de idioma for qualquer outro código de idioma (incluindo de-DE e de-CH) e" Olá, Mundo! "quando seu código de idioma for qualquer outra coisa. Se uma string for ausente na versão localizada, o gerenciador de recursos passará automaticamente pela cadeia, do recurso mais especializado ao invariante.
Você pode usar a ResourceManager
classe para ter mais controle sobre como exatamente está carregando as coisas. A Strings
classe gerada também a usa.
Além disso, a ótima resposta de @Fredrik Mörk sobre cadeias de caracteres, para adicionar localização a um formulário, faça o seguinte:
"Localizable"
comotrue
Language
propriedade do formulário para o idioma desejado (em um bom menu suspenso com todos eles dentro)Edit: Este artigo do MSDN sobre Localização de formulários do Windows não é o original que vinculei ... mas pode lançar mais luz se necessário. (o antigo foi levado embora)
Ótima resposta de F.Mörk. Mas se você deseja atualizar a tradução ou adicionar novos idiomas assim que o aplicativo é lançado, você fica paralisado, porque sempre é necessário recompilá-lo para gerar os recursos.dll.
Aqui está uma solução para compilar manualmente uma dll de recurso. Ele usa as ferramentas resgen.exe e al.exe (instaladas com o sdk).
Digamos que você tenha um arquivo de recurso Strings.fr.resx, você pode compilar uma DLL de recursos com o seguinte lote:
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
Certifique-se de manter o espaço para nome original nos nomes dos arquivos (aqui "WpfRibbonApplication1")
Uma correção e elaboração da resposta do @Fredrik Mörk .
strings.resx
arquivo de recursos ao seu projeto (ou um nome de arquivo diferente)Access Modifier
como Public
(na strings.resx
guia arquivo aberto )Hello
, valor Hello
)O Visual Studio gera automaticamente uma strings
classe respectiva , que é realmente inserida strings.Designer.cs
. A classe está no mesmo espaço para nome em que você esperaria que um .cs
arquivo recém-criado fosse colocado.
Esse código sempre é impresso Hello
, porque este é o recurso padrão e nenhum recurso específico ao idioma está disponível:
Console.WriteLine(strings.Hello);
Agora adicione um novo recurso específico ao idioma:
strings.fr.resx
(para francês)Hello
, valor Salut
)O código a seguir é impresso Salut
:
Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("fr-FR");
Console.WriteLine(strings.Hello);
Qual recurso é usado depende Thread.CurrentThread.CurrentUICulture
. É definido dependendo da configuração do idioma da interface do usuário do Windows ou pode ser definido manualmente, como neste exemplo. Saiba mais sobre isso aqui .
Você pode adicionar recursos específicos de país como strings.fr-FR.resx
ou strings.fr-CA.resx
.
A cadeia a ser usada é determinada nesta ordem de prioridade:
strings.fr-CA.resx
strings.fr.resx
strings.resx
Observe que recursos específicos de idioma geram assemblies de satélite .
Aprenda também como CurrentCulture
difere CurrentUICulture
daqui .
Além de @Eric Bole-Feysot :
Graças aos assemblies de satélite, a localização pode ser criada com base nos arquivos .dll / .exe . Deste jeito:
Existe uma ferramenta pouco conhecida chamada LSACreator (gratuita para uso não comercial ou opção de compra) que permite criar a localização com base em arquivos .dll / .exe. De fato, internamente (no diretório do projeto de idioma) ele cria / gerencia versões localizadas de arquivos resx e compila um assembly de maneira semelhante à descrita por @Eric Bole-Feysot .
ResourceManager e .resx são um pouco confusos.
Você pode usar o Lexical.Localization ¹, que permite incorporar o valor padrão e os valores específicos da cultura no código, e ser expandido em arquivos de localização externos para outras culturas (como .json ou .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) );
}
}
I'm (eu sou mantenedor dessa biblioteca)
Em geral, você coloca suas traduções em arquivos de recursos, por exemplo, resources.resx.
Cada cultura específica tem um nome diferente, por exemplo, resources.nl.resx, resources.fr.resx, resources.de.resx,…
Agora, a parte mais importante de uma solução é manter suas traduções. No Visual Studio, instale a ferramenta Microsoft MAT: Multilingual App Toolkit (MAT). Funciona com winforms, wpf, asp.net (core), uwp,…
Em geral, por exemplo, para uma solução WPF, no projeto WPF
[assembly: System.Resources.NeutralResourcesLanguage("en")]
O que você verá é que uma nova pasta será criada, chamada "MultilingualResources" contendo um ....nl.xlf
arquivo.
A única coisa que você precisa fazer agora é:
(os arquivos .xlf devem abrir com o "Editor multilíngue", se esse não for o caso, clique com o botão direito do mouse no arquivo .xlf, selecione "Abrir com ..." e selecione "Editor multilíngue".
Diverta-se! agora você também pode ver o que não foi traduzido, exportar traduções em xlf para empresas de tradução externas, importá-las novamente, reciclar traduções de outros projetos etc.
Mais informações: