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.