2008-11-24 9 views
7

Tener una aplicación totalmente internacionalizada es una necesidad si desea vender en todo el mundo. En Java estamos utilizando paquetes de recursos y eso resuelve las cosas para el código de barras de texto estático.¿Cómo internacionalizas el texto en la base de datos?

Pero, ¿qué haces con el texto que está almacenado en la base de datos? Comenzando con las definiciones estáticas, los objetos modificables por el usuario y finalizando con los datos ingresados ​​por el usuario.

Suponiendo que tiene una base de datos utilizada por usuarios con configuraciones regionales diferentes, ¿cómo maneja esto? ¿Qué tan lejos se internacionaliza? ¿Dónde se traza la línea? ¿Qué solución puede evitar que los usuarios reciban texto en un idioma que no entienden?

Respuesta

6

No guarde el texto generado por el sistema en la base de datos. En su lugar, almacene un código (como un número de mensaje) y luego internacionalícelo en el nivel de la GUI. Asegúrese de que el único texto que sale directamente de la base de datos es el texto que el usuario coloca en sí mismo. Asegúrese de que su base de datos esté configurada para aceptar texto unicode.

0

Los datos estáticos son los más sencillos que crearía una tabla de traducción, así que imagine una tabla UserStatus que tenga un StatusId, TranslationToken, luego la tabla de traducción tiene un token, un idioma y texto.

O simplemente, puede devolver el token para que la aplicación lo procese utilizando sus archivos de recursos.

En cuanto a los datos de entrada del usuario, esto es mucho más complejo. Debe aceptar caracteres Unicode como mínimo, pero luego la pregunta se convierte en Ordenar y Comparar. La clasificación es la más grande. Mucho de lo que puede hacer depende de su aplicación. Entonces, si su base de datos solo tiene que admitir un solo idioma en algún momento (imagine si su aplicación se distribuyó a sus clientes), la intercalación es un punto discutible ya que puede configurarlo en el momento de la instalación.

Sin embargo, si tiene que admitir varios idiomas en una sola base de datos, deberá manejar la intercalación correctamente. La única forma en que encontramos para cambiar la intercalación sobre la marcha fue establecerla dentro de nuestras consultas, y eso requería que se generase sql dinámico. Este ejemplo sería que está almacenando ruso, inglés y polaco, todo en un solo campo en la misma tabla.

Nunca exploramos nada más allá de las colaciones latinas y cirílicas, pero me imagino que los idiomas asiáticos funcionarían de la misma manera.

0

Utilizamos archivos XML para nuestro sistema. El archivo contiene asociaciones de teclas con partes específicas de nuestros módulos. De esta forma, podemos hacer XPath rápidamente para recuperar información. Tenemos 1 archivo para cada idioma (admitimos 2 idiomas por el momento, pero agregar un idioma es muy simple, simplemente copie y pegue el archivo). Esta solución no es perfecta, pero tiene algunas ventajas:

  1. No en la base de datos.
  2. Puede ser editado por alguien externo a la programación.
  3. Fácil de implementar en múltiples vistas (tenemos WinForm y WebForm).
1

Qué solución puede evitar que los usuarios recibir mensajes de texto en un idioma que no entienden ?

Eso solo sería un problema para los datos ingresados ​​por el usuario.Por lo tanto, si desea evitar que otros usuarios vean contenido en un idioma que quizás no entiendan, almacene el código de configuración regional junto con el contenido y solo muestre ese contenido a cualquier persona que tenga el mismo idioma elegido por el lugar/usuario.

Por otro lado, los usuarios pueden conocer varios idiomas para no restringirlos de ver contenido, solo agregaría un aviso como "Este contenido no está disponible en el idioma de su elección, ..." y luego mostrar el contenido en el idioma disponible. De esta forma aumenta la probabilidad de que el usuario obtenga un contenido que pueda entender.

2

En primer lugar, tenga en cuenta las limitaciones. Para el contenido creado por el usuario, está buscando la traducción de la comunidad (errática), la traducción automática (no confiable) o el pago de traductores humanos (¡caros!) Si desea localizar las cosas que los usuarios ingresan en su aplicación. Es posible que desee solicitar a sus usuarios que proporcionen dos versiones, una para su cultura predeterminada (¿inglés?) Y otra para su cultura localizada, para que pueda proporcionar una traducción alternativa para otros usuarios.

En segundo lugar, prepárese para migraciones de bases de datos extremadamente largas ... si tiene cuatro columnas de texto en una hoja de cálculo de Excel, de repente se trata de insertar cada valor en su sistema de traducción, recuperar la ID localizada, y luego almacenar que en la tabla que está realmente importando, y SELECT * solo le dará identificadores de frase, que debe resolver de nuevo en cadenas localizándolos en sus tablas de traducción.

Dicho esto: puede localizar muchas de las tablas de búsqueda, listas desplegables, etc. que maneja la base de datos en un proyecto típico. Otros comentarios ya han mencionado el almacenamiento de valores de StringId en la base de datos que hacen referencia a archivos de recursos externos u hojas de cálculo, pero si está interesado en mantener TODO su texto localizado en la base de datos junto con los datos, tal vez le resulte útil este enfoque.

Hemos utilizado una tabla llamada Frase, que contiene la ID y el contenido predeterminado (en inglés) para cada texto de la aplicación.

Sus otras mesas terminan pareciéndose a esto:

CREATE TABLE ProductType (
    Id int primary key, 
    NamePhraseId int, -- link to the Phrase containing the name of this product type. 
    DescriptionPhraseId int 
) 

crear una segunda tabla de Cultura, que contiene las culturas específicas y neutrales que estés de apoyo. Para obtener puntos de bonificación, implemente esta tabla como un árbol autorreferencial (cada registro de Cultura contiene una referencia de NullCripCultureCode), de modo que puede retroceder de culturas específicas ("fr-CA" para el francés canadiense) a culturas neutrales ("fr" si no existe una localización regional), a su referencia cultural de todos/defecto (normalmente, 'es' porque es tan ampliamente hablado)

sus traducciones reales están en una mesa LocalizedPhrase, que se parece a:

CREATE TABLE LocalizedPhrase (
    PhraseId int primary key, 
    CultureCode varchar(8) primary key, 
    Content nvarchar(255) -- the actual localized content 
) 

puede extienda este modelo si desea proporcionar localizaciones específicas para hombres/mujeres:

CREATE TABLE GenderedLocalizedPhrase (
    PhraseId int primary key, 
    CultureCode varchar(8) primary key, 
    GenderCode char(1) primary key, -- 'm', 'f' or '?' - links to Gender table 
    Content nvarchar(255) 
) 

Querrá guardar en caché todo el gráfico de la tabla en memoria y modificar sus estrategias de consulta/unión en consecuencia: almacenar en memoria caché las localizaciones dentro de las clases de Frases y reemplazar el método ToString() en el objeto Frase para inspeccionar la cultura del hilo actual. Si tratas de hacer estas cosas dentro de sus consultas, se incurrirá en un costo sustancial el rendimiento y cada consulta va a terminar con este aspecto:

-- assume @MyCulture contains the culture code ('ca-FR') that we are looking for: 
SELECT 
    Product.Id, 
    Product.Name, 

    COALESCE(ProductStatusLocalizedPhrase.Content, ProductStatusPhrase.Content) as ProductStatus, 
    COALESCE(ProductTypeLocalizedPhrase.Content, ProductTypePhrase.Content) as ProductType, 
    FROM Product 

    INNER JOIN ProductStatus ON Product.StatusId = ProductStatus.Id 
    INNER JOIN Phrase as ProductStatusPhrase ON ProductStatus.NamePhraseId = Phrase.Id 
    LEFT JOIN LocalizedPhrase as ProductStatusLocalizedPhrase 
     ON ProductStatus.NamePhraseId = ProductStatusLocalizedPhrase.Id and CultureCode = @MyCulture 

    INNER JOIN ProductType ON Product.TypeId = ProductType.Id 
    INNER JOIN Phrase as ProductTypePhrase ON ProductType.NamePhraseId = Phrase.Id 
    LEFT JOIN LocalizedPhrase as ProductTypeLocalizedPhrase 
     ON ProductType.NamePhraseId = ProductTypeLocalizedPhrase.Id and CultureCode = @MyCulture 
1

Estamos cambiando una gran parte del texto en nuestra base de datos para ser “ clave: texto predeterminado "y luego buscar la" clave "en nuestros archivos de traducción.Esto cubre todo el texto que el cliente no cambia en la base de datos (por ejemplo, qué llamar "nota de crédito"). Cuando el cliente cambia el texto, simplemente puede quitar la clave, de modo que siempre obtenga el valor.

Nuestro sistema tiene algunas tablas que contienen datos de configuración que necesitan lo anterior, las tablas que solo contienen texto que los clientes ingresan no son un problema si cada cliente solo necesita un idioma.

1

Digamos que usted tiene una tabla:

create table countries (
    country_id int primary key, 
    short_name text not null unique, 
    official_name text not null unique, 
    iso_code char(2) not null unique 
); 

insert into countries values (12, 'Algeria', 'The People''s Democratic Republic of Algeria' 'DZ'); 

A continuación, se crea una tabla de traducción:

create table countries_t (
    country_id int not null references countries(country_id), 
    short_name text not null, 
    official_name text not null, 
    locale varchar(5) not null, 

    primary key (country_id, locale) 
); 

insert into countries_t values 
(12, 'Algérie', 'la République algérienne démocratique et populaire', 'fr'), 
(12, 'Algerien', 'Demokratische Volksrepublik Algerien', 'de-DE'); 

crear una vista para devolver los datos basados ​​en una user - defined variable de sesión. A continuación se muestra-PostgreSQL específico, pero su base de datos podría apoyar las variables de sesión personalizados, otro cuadro de utilización temporal:

create view countries_i18n as 
    select 
    a.country_id, 
    coalesce(c.short_name, b.short_name, a.short_name) as short_name, --default to countries.name if translation not found 
    coalesce(c.official_name, b.official_name, a.official_name) as official_name 
    countries.iso_code 
    from countries a 
    left join countries_t b on b.id = a.id and b.locale = current_setting('my_custom_guc.locale') 
    left join countries_t c on c.id = a.id and c.locale = left(current_setting('my_custom_guc.locale'), 2); --fall-back to 2-letter locale 

consultar la tabla en alemán que se habla en Alemania:

SET my_custom_guc.language_code = 'de-DE'; 

select country_id, iso_code, short_name, official_name from countries_i18n; 

country_id iso_code short_name official_name 
----------------------------------------------- 
12   DZ  Algerien Demokratische ... 

consultar la tabla en francés canadiense (cae de nuevo al genérico francés):

SET my_custom_guc.locale= 'fr-CA'; 

select country_id, iso_code, short_name, official_name from countries_i18n; 

country_id iso_code short_name official_name 
----------------------------------------------- 
12   DZ  Algérie  la République ... 

consultar la tabla en español (no hay traducción, regresa Inglés):

SET my_custom_guc.language_code = 'es'; 

select country_id, iso_code, short_name, official_name from countries_i18n; 

country_id iso_code short_name official_name 
----------------------------------------------- 
12   DZ  Algeria The People's D ... 
Cuestiones relacionadas