Estratégias eficazes para localização no .NET [fechado]


121

Estou desenvolvendo a interface do usuário para um aplicativo .NET MVC que exigirá a localização internacional de todo o conteúdo em um futuro próximo. Conheço muito bem o .NET em geral, mas nunca tive um projeto que exigisse um foco tão significativo na acessibilidade internacional.

O projeto está sendo feito inicialmente em inglês. Que medidas devo tomar neste momento para facilitar a implementação da localização no futuro?


2
Ótima pergunta! Estou enfrentando uma situação semelhante e gostaria de ver os especialistas analisando isso.

Alguém tem bons padrões para gerenciamento de recursos? O valor localizado também pode incluir imagens, e não apenas seqüências de caracteres.

1
Esta é uma interface do usuário do WPF / silverlight ou WinForms? Da minha experiência (limitada), a experiência do WinForms para localização é muito mais simples que o WPF / Silverlight.
Pete Stensønes

1
Se você acabar armazenando suas seqüências de caracteres localizadas no banco de dados, em vez de arquivos de recursos, dê uma olhada nesta discussão: stackoverflow.com/questions/2458615/…

1
@Pete, @smartcaveman disse que está "desenvolvendo a interface do usuário para um aplicativo .NET MVC", então ...
BrunoSalvino

Respostas:


74

Você está desenvolvendo o aplicativo ASP.Net MVC, não é? Outras respostas parecem ser específicas para aplicativos de desktop. Deixe-me capturar coisas comuns:

Detecção de localidade

É muito importante que seu aplicativo detecte a localidade do usuário corretamente. No aplicativo de desktop, CultureInfo.CurrentCulture mantém o código de idioma de formatação preferido (aquele que deve ser usado para formatar números, datas, moedas etc.), enquanto CultureInfo.CurrentUICulture mantém o código de idioma de interface do usuário preferido (aquele que deve ser usado para exibir mensagens localizadas) . Para aplicativos da Web, você deve configurar as duas culturas como automáticas (para detectar automaticamente a localidade do cabeçalho AcceptLanguage), a menos que queira implementar algum fluxo de trabalho sofisticado de detecção de localidade (por exemplo, deseja oferecer suporte à alteração do idioma sob demanda).

Externalizar strings

Todas as strings devem vir de recursos, ou seja, arquivos Resx. No aplicativo Winforms, é facilmente possível definir a propriedade Localizable do formulário como true. Você também precisará externalizar manualmente (infelizmente) as strings que vêm de seus modelos. Também é relativamente simples. No Asp.Net, você precisaria externalizar tudo manualmente ...

Layouts

Você definitivamente precisa permitir a expansão de strings. No mundo Winforms, é possível via TableLayoutPanel, que deve ser usado para garantir que o layout seja ajustado automaticamente para acomodar textos mais longos. No mundo da web, você está um pouco sem sorte. Pode ser necessário implementar o Mecanismo de localização CSS - uma maneira de modificar (substituir) as definições CSS. Isso permitiria que o pessoal da localização modificasse os problemas de estilo sob demanda. Certifique-se de que cada elemento HTML da página renderizada tenha um ID exclusivo - ele permitirá segmentá-lo com precisão.

Questões específicas da cultura

Evite usar gráficos, cores e sons que possam ser específicos para a cultura ocidental. Se você realmente precisar, forneça meios de localização. Evite gráficos sensíveis à direção (pois isso seria um problema ao tentar localizar para dizer árabe ou hebraico). Além disso, não assuma que o mundo inteiro está usando os mesmos números (ou seja, não é verdade para o árabe).

ToString () e Parse ()

Certifique-se de sempre passar CultureInfo ao chamar ToString (), a menos que não seja suportado. Dessa forma, você está comentando suas intenções. Por exemplo: se você estiver usando algum número internamente e por algum motivo precisar convertê-lo em string, use:

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

Para números que serão exibidos para uso do usuário:

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

O mesmo se aplica a Parse (), TryParse () e até ParseExact () - alguns erros desagradáveis ​​podem ser introduzidos sem o uso adequado de CultureInfo. Isso ocorre porque uma alma pobre da Microsoft, cheia de boas intenções, decidiu que é uma boa idéia tratar CultureInfo.CurrentCulture como padrão (ele seria usado se você não passar nada) - afinal, quando alguém está usando o ToString ( ) ele / ela quer exibi-lo para o usuário, certo? Acontece que nem sempre é o caso - por exemplo, tente armazenar o número da versão do aplicativo no banco de dados e depois convertê-lo em instância da classe Version. Boa sorte.

Datas e fusos horários

Certifique-se de sempre armazenar e instanciar DateTime no UTC (use DateTime.UtcNow em vez de DateTime.Now). Converta-o para a hora local no formato local ao exibir:

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

Se você precisar enviar e-mails com referência de horário no corpo, inclua informações de fuso horário - inclua o deslocamento UTC e a lista de cidades:

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

Mensagens compostas

Você já foi avisado para não concatenar seqüências de caracteres. Em vez disso, você provavelmente usaria String.Format () como mostrado acima. No entanto, devo declarar que você deve minimizar o uso de mensagens compostas. Isso ocorre porque as regras gramaticais de destino geralmente são diferentes, portanto, os tradutores podem precisar não apenas reordenar a sentença (isso seria resolvido usando espaços reservados e String.Format ()), mas traduzir a sentença inteira de maneira diferente, com base em o que será substituído. Deixe-me dar alguns exemplos:

// 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ę.

Outros problemas de concatenação

A concatenação não está restrita a seqüências de caracteres. Evite colocar os controles juntos, diga:

Lembre-me novamente em [caixa de texto com número] dias.

Isso deve ser redesenhado para algo como: Lembre-me novamente neste número de dias: [caixa de texto].

Codificação de caracteres e fontes

Sempre salve, transfira qualquer texto em Unicode (ou seja, em UTF-8). Não codifique as fontes - a localização pode precisar modificá-las e desativará o mecanismo de fallback de fonte padrão (no caso do WinForms). Lembre-se de permitir caracteres "estranhos" na maioria dos campos (nome do usuário).

Teste

Você provavelmente precisará implementar a chamada pseudo tradução, ou seja, criar recursos para a cultura alemã, como por exemplo, e copiar suas seqüências em inglês, adicionando prefixo e sufixo. Você também pode agrupar espaços reservados para detectar facilmente cadeias compostas. O objetivo da pseudo-tradução é detectar problemas de Localizabilidade, como sequências codificadas, problemas de layout e uso excessivo de mensagens compostas.


5
Em relação às mensagens compostas - eu tive que fazer várias formas do plural uma vez. Eu estendi String.Formatpara que pudesse suportar esta sintaxe legal: "There {0:was|were} {0} {0:virus|viruses} found."Cada idioma pode carregar suas próprias regras, então você poderia fazer "Znaleziono {0} {0:wirusy|wirusów}." A fonte está no GitHub: github.com/scottrippey/SmartFormat/wiki
Scott Rippey

2
@ Scott Rippey Você já reparou que o exemplo em polonês diz "Znaleziono 4 wirusy. OU Znaleziono 5 wirusów". <- O polonês, como muitas outras línguas, tem mais de duas formas plurais e as regras para distinguir entre elas também podem ser complexas. Aqui devo deixar o polonês, pois não o falo, mas na minha língua a forma plural de 101 coisas é a mesma de uma coisa. Você pode dar uma olhada em tackles gettext como GNU este problema: gnu.org/s/hello/manual/gettext/Plural-forms.html
gregopet

2
@gregopet Meu exemplo em polonês foi artificial, porque eu não falo, mas é exatamente isso que o projeto SmartFormat faz. Aqui está um exemplo melhor: "{0} {0:plik|pliki|plików}". O formatador possui uma regra polonesa que determina qual das 3 formas usar e determina corretamente os casos especiais. Atualmente, estou trabalhando para adicionar mais regras, portanto, o gettextartigo será muito útil, obrigado.
22811 Scott Rippey

Para pseudolocalization, eu construí uma ferramenta gratuita on-line pseudolocalization em pseudolocalize.com
JerSchneid

74

Algumas coisas básicas que você deve levar em consideração:

Externalizar todos os recursos de sequência

Todos os seus recursos devem estar contidos em arquivos externos que podem ser transferidos para localização. Não se esqueça das mensagens de erro, se você quiser localizá-las também.

Permitir espaço suficiente para expansão de string

As seqüências em alguns idiomas tendem a ser até 30% mais longas (como o grego), por exemplo, portanto, garanta que você projete sua interface do usuário de forma que as cadeias possam se expandir, se necessário. Aqui está um exemplo extremo para o francês:

Ok -> Aceitador (francês - expansão de 400%)

Eu recomendo fazer algum tipo de pseudo-tradução como ponto de partida ( http://en.wikipedia.org/wiki/Pseudolocalization ). Ou você pode traduzir seus recursos via Google Translate ou Bing. Isso fornecerá uma boa indicação de como serão as traduções reais.

Cuidado com o texto nas imagens

Se você usar imagens em seu aplicativo - verifique se elas não contêm texto - isso obviamente não pode ser traduzido.

Nunca codifique nenhum caminho para as pastas do Windows

Óbvio, mas eu já vi isso no passado. Por exemplo, C:\Program Filesé traduzido em algumas versões internacionais do Windows, por exemplo, C:\Programmeem um sistema operacional alemão.

Evite usar termos específicos de localidade

Por exemplo, se você pedir a alguém a sua 'High School' em um formulário, isso terá pouco significado na Europa Ocidental.

Evite criar strings via concatenação de strings

Por exemplo, isso parece inofensivo:

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

Porém, a ordem das palavras em japonês, por exemplo, seria diferente; portanto, isso pode acabar não fazendo sentido.

Configurações de hora / data

Sempre certifique-se de obter o formato de hora / data no SO.


@ Jimmy C, como você constrói seqüências de caracteres para obter consistência lógica independente da linguagem?
smartcaveman

14
@ Smart faça algo em seu recurso como "{0}, {1}"; quando você o localizar, use string.format e passe a saudação e o nome de usuário. Além disso, isso lhe dá o benefício de ter "A velocidade atual {0} é {1} {2}" e você pode passar "Motor", "50" e "MPH" e, ao traduzir sua frase, você pode mover { 0} etc volta para onde eles fazem sentido em que a linguagem
taylonr

4
Boa lista JimmyC. "Nunca codifique nenhum caminho para as pastas do Windows" me lembrou "Sempre use Path.Combine" em vez da concatenação de strings para os caminhos do Windows.

@ Jimmy-C Ótima resposta!

1
O Environment.GetFolderPath pode ser usado para obter caminhos válidos para caminhos comuns, como Meus documentos, sem depender do nome em inglês dessas pastas.
Crippledsmurf

24

Considerações especiais para idiomas asiáticos

Além de todas as ótimas respostas já disponíveis, alguns atentados aos idiomas asiáticos:

Cuidado com diferentes comprimentos de texto

O texto em chinês e coreano tende a ser muito menor que o texto equivalente em inglês (já que geralmente você precisa de menos caracteres em bloco para escrever a mesma coisa), portanto, uma página pode parecer vazia em chinês, mas cheia em alemão ... Você precisa algum dimensionamento dinâmico aqui para ter uma boa aparência.

No entanto, o texto em japonês geralmente tende a ser muito mais longo, ainda mais que o equivalente em inglês em termos de contagem de caracteres.

Cuidado com o layout da linha de base e a aparência "deslizada para cima"

Os caracteres asiáticos geralmente são dispostos na linha de base , que não incluem descendentes (ou seja, a parte inferior de y, g, q, j etc.) Quando você formata um elemento da tela - geralmente botões - com texto dentro e se isso como o texto é apenas em idiomas asiáticos (ou seja, sem alfabetos ocidentais), o texto parecerá deslocado para cima.

Formatação de números e unidades numéricas localizadas

Manipule a formatação de números de maneira diferente. Diferentes países asiáticos têm maneiras diferentes de formatar números. Mesmo com moedas. Por exemplo, no leste da Ásia, 10.000 (wan) é uma unidade comum. Na Índia, 100.000 (lakhs) são comuns.

Moedas locais

As moedas de alguns países têm muitos zeros e nenhum ponto decimal (por exemplo, Japão, Indonésia, Itália), enquanto outros têm até dois dígitos após o ponto decimal.

Cuidado com ordens de palavras diferentes

A ordem das palavras nem sempre pode ser a mesma. É melhor usar {0}, {1} etc. na formatação de strings, em vez de codificar por ordem de palavras, se sua string vier de uma combinação de diferentes partes de dados.

Usar classificação específica de localidade

A classificação é diferente por idioma e por localidade - você deve sempre confiar na classificação específica da localidade do O / S.

Seja muito cauteloso com caracteres de largura total / meia largura

Cuidado com as diferenças entre os caracteres "largura total" e "meia largura". Os colchetes, a pontuação etc. podem ter versões "de largura total" diferentes do ASCII padrão. Se você pesquisar ou dividir cadeias com base nessas letras, primeiro será necessário converter todos os símbolos de largura total em equivalentes de meia largura.

Um ponto não é um ponto ... uma vírgula não é uma vírgula ...

Cuidado com as dicas de entrada de dados - por exemplo, em chinês, um período não é um ponto ".". Uma vírgula é de largura total, não ",". Não tente procurar pontuação ocidental se o usuário que faz a entrada de dados acidentalmente ativar o IME no idioma asiático.

Números de telefone

Não assuma nada na formatação de número de telefone. Nem sempre existe um código de área, etc., e ele pode ser formatado de maneira diferente. Geralmente, tem uma sequência de formato por país.

Não presuma que as pessoas terão apenas um número de telefone celular ou um número de fax etc. Não é assim na Ásia.

Endereços - mais densos do que você imagina

Para endereços, não assuma nada . Nem sempre pode haver um código postal. Os códigos postais nem sempre podem ser números. Um país pode não ter províncias / estados. Um país pode ser apenas uma cidade grande (por exemplo, Cingapura). Para certos países asiáticos, a menor unidade de uma casa pode ser "Sala X, Unidade Y, Seção Z, Piso A, Bloco B, Grupo C, Bairro D". Em geral, seja muito liberal no número de campos e no número de caracteres permitidos nos endereços.

Saudações

Saudações não estão restritas apenas ao Sr., Sra etc. Embora provavelmente você está seguro em usar "M" e "F" para o sexo - não somos que estranho ainda ...


1
O último parágrafo me fez sorrir.
BoltClock

Ah, nós (pessoal da i18n) ainda nem começamos ... Só conseguimos arranhar a superfície :) Se falássemos sobre questões específicas, como o suporte GB18030, nossa postagem seria muito longa para SO lidar com isso :) Obrigado de qualquer maneira, para a sua anotação, perdi alguns itens.
Paweł Dyda

Sobre o último, acredito que o Reino Unido agora aceite oficialmente "Outro" como sexo. Pense transgêneros.
Bart Friederichs

11

Algumas etapas básicas são garantir que qualquer string exibida na tela não seja literal no seu código. Se você estiver executando o Winforms, cada formulário terá um recurso de interface do usuário. Para diálogos, relatórios, etc, certifique-se de usar os arquivos de recursos do projeto.

Portanto, em vez de "Falha no upload" no seu código, você pode ter algo como Resources.UploadFailed

Dessa forma, você pode criar um novo arquivo de recurso para cada idioma usado (e o .Net ajudará nisso.) E ter a string localizada em cada arquivo.

EDITAR Esqueci de mencionar quando você está fazendo sua interface do usuário, certifique-se de não colocar apenas as coisas lá. Dependendo dos idiomas em que você está localizando, o setor imobiliário pode ser um problema. Eu trabalhei em um projeto que tinha alemão e português como os 2 maiores infratores do crescimento de cadeias. Se não tivéssemos cuidado com as cordas que estavam bem em inglês, francês e italiano explodiriam em alemão.


1
Da minha experiência com L10n, o russo é o pior cenário. No entanto, no WinForms com o usuário adequado do TableLayoutPanels, é possível lidar com o crescimento de cadeias normalmente.
Paweł Dyda

Sim, minha experiência foi limitada a 7 idiomas: inglês, alemão, português, italiano, francês, espanhol e japonês. Mas eu posso ver russo sendo ruim como eles tendem a ter um monte de sufixos e prefixos
taylonr

9

Eu sugiro que você execute FXCop ou Visual Studio Code Analysis (eles são iguais) em seus assemblies.

Eles são bons em detectar código .NET que não usa as sobrecargas orientadas a cultura apropriadas, como esta: CA1305: Especifique IFormatProvider .

Devo acrescentar que essas ferramentas também são frustrantes porque geralmente detectam zilhões de problemas em seu código, mas, mesmo que você não siga cada regra, você deve aprender muito.


Esse é o padrão ou preciso especificar alguma configuração para procurar regras específicas da globalização?
smartcaveman

@smartcaveman - é o padrão (hmm .. na verdade, algumas pessoas pensam que existem regras padrão de reboque muito nestas ferramentas :-)
Simon Mourier

7

Além do específico sobre como carregar recursos, certifique-se de testar com uma versão pseudo-localizada para começar. Caso contrário, você provavelmente não perceberá os lugares em que as considerações de internacionalização foram omitidas até o final.


Para uma maneira rápida, fácil de pseudolocalize, eu construí uma ferramenta online gratuita em pseudolocalize.com
JerSchneid

6

Além de todas as outras dicas úteis, aqui estão algumas que estão faltando:

Leve em consideração que alguns países usam mais de um idioma. Por exemplo, no Canadá, um usuário esperaria poder alternar facilmente entre inglês e francês.

Se você perguntar ao usuário uma pergunta que espera uma resposta de uma única letra, não espere que o usuário pressione a tecla 'Y' para dizer Sim.

Esteja ciente dos procs armazenados de que as datas no banco de dados SQL estão no formato EUA

A colocação de cadeias de texto no banco de dados permite adicionar idiomas adicionais posteriormente sem reimplementar.

Ao enviar arquivos de texto escritos para tradução, sempre inclua uma descrição do contexto para garantir que o tradutor selecione a palavra correta. Por exemplo, sem contexto, você pode traduzir "pitch:" em algo relacionado ao som ou a um local em que você joga futebol

As etiquetas de endereço sempre precisam ser convertidas. Província no Canadá, Estado na América, Condado no Reino Unido


5

Você precisa considerar:

  1. Roteamento para vários idiomas

  2. Mova toda a cadeia de código rígido para o arquivo de recursos

Um exemplo para uma propriedade:

Modelo:

[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; }

Visão:

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

5

Aqui está algo não mencionado no restante das respostas.

Dependendo da complexidade do seu aplicativo e sua localização, recomendo a implementação de um provedor de recursos alternativos e a manutenção de recursos localizados em um banco de dados. Com o esquema de localização padrão do ASP.NET, todos os recursos são mantidos em arquivos RESX, que:

  1. É problemático editar no Visual Studio
  2. Limite a distribuição e o gerenciamento de recursos localizados após a compilação / envio / execução do aplicativo.

Como possível caso de uso, considere fornecer pacotes de idiomas para seu aplicativo e a capacidade de importar e exportar idiomas por meio da interface do usuário. Arquivos RESX não ajudariam aqui.

Em cenários como esse, um provedor de recursos alternativos é muito útil. Mais informações sobre como implementar uma podem ser encontradas aqui . Obviamente, esse é um caso raro, mais comumente visto em aplicativos corporativos, mas ainda válido.


1
Obrigado por reservar um tempo para analisar essas ótimas respostas e ainda contribuir com algo novo e útil.
smartcaveman

+1; Eu construí uma aplicação web extensa no Asp.NET e acabamos fazendo traduções através do banco de dados. Novos recursos eram frequentemente adicionados, mas como nossos tradutores não eram especialistas na terminologia específica usada, pudemos responder rapidamente a e-mails irritados de clientes do tipo "Por que você está usando a palavra Y para X que está claramente errada?".
gregopet

3

O mais importante é gerenciar o conteúdo em vários idiomas. Eu mesmo desenvolvi algumas websistes e gerenciar o conteúdo em vários idiomas é o maior desafio.

Estou usando o banco de dados para armazenar os recursos / conteúdo. Isso me dá a flexibilidade de adicionar qualquer suporte de idioma que eu desejar. Eu implementei a lógica de voltar ao idioma inglês se um recurso em determinado idioma não for encontrado.

Posteriormente, você pode usar um tradutor para converter o valor do inglês em qualquer idioma.


2

Resumo das coisas a considerar na internacionalização:

  • Todas as informações devem ser internacionalizadas. Leve em consideração que os gráficos podem ter informações que queremos internacionalizar.

  • O tamanho dos campos ou seqüências de caracteres, dependendo do idioma, pois pode nos causar um problema.

  • A ordem das palavras depende do idioma que somos, portanto, uma ordem em um idioma será a mesma em outro.

  • Devemos levar em conta que o formato da data mudará de um idioma para outro


1

Faça o teste da Turquia :

A internacionalização de software é difícil nas melhores circunstâncias , mas sempre me surpreendeu a frequência com que um determinado país surgiu nas discussões sobre problemas de internacionalização: Turquia ...

Se você se preocupa com a localização ou a internacionalização, force o código a ser executado no código de idioma turco o mais rápido possível . É um forte argumento para o seu código sendo executado na maioria - mas de nenhuma maneira - culturas e locais ...

Se o seu site / programa funcionar bem com um cliente turco, você pode ter certeza de que será executado na maioria das outras plataformas.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.