cocoa - software - Localización de una aplicación Mac moderna basada en xib
permitir instalar aplicaciones de origen desconocido mac sierra (4)
Confieso que no estoy tan familiarizado con el proceso de localización de aplicaciones de Mac. Pero sí encontré un script que forma parte de la biblioteca de iPhone Three20 que parece ser útil: diffstrings.py es un script de Python que "compara su configuración regional principal con todas las demás configuraciones regionales para ayudarlo a determinar qué nuevas cadenas deben ser traducido. Produce archivos XML que se pueden traducir y luego fusionar de nuevo en sus archivos de cadenas ".
EDITAR: Como complemento de la respuesta de Wil Shipley a esta pregunta, agregaré un enlace a wilshipley.com/blog/2009/10/pimp-my-code-part-17-lost-in.html que brinda más detalles sobre la localización y proporciona algunas de las herramientas que ha creado para facilitar el proceso.
La nuestra es una aplicación de código abierto para Mac localizada por voluntarios. Estos voluntarios realizarán su trabajo en compilaciones de localización especiales del software (con pliegues sin marcar) y luego nos enviarán los cambios para integrarlos en los archivos de cadenas y xib originales.
El problema es que, si bien hay una manera de integrar los cambios de cadena sin eliminar los cambios de tamaño anteriores , no puedo ver una forma de integrar los nuevos cambios de cadena y tamaño (como cuando agregamos o reemplazamos vistas).
La única forma de hacer las dos cosas que puedo ver es que los localizadores trabajen directamente con los xibs originales y nos envíen diffs. Eso significa que tienen que descargar el código fuente completo, no solo una versión localizable del lanzamiento, trabajar en Xcode y IB, y ejecutar el comando diff (por xib) o instalar y usar Mercurial.
¿Hay alguna forma mejor para una aplicación basada en xib?
Donde solía trabajar, también teníamos este problema. Nuestra aplicación fue traducida a 10 idiomas diferentes.
Al principio, intentamos hacer lo que Wil sugirió, que es hacer que todo sea súper amplio y que se ajuste a todos los idiomas. Desafortunadamente, la "copia de seguridad en línea" puede ser bastante breve en inglés, pero en otros idiomas (especialmente en español), es realmente larga ("copia de seguridad" solo significa "copia de seguridad"). Ampliar nuestra interfaz de usuario hizo que todo se viera bastante terrible.
Un día, estaba jugando con algunas cosas de Core Animation y descubrí la clase CAConstraint
. CAConstraint
es básicamente una forma de definir una relación de diseño entre dos CALayers
. Usted le asigna un nombre a una capa (como "layerA") y luego dice que "layerB está restringido [de tal o cual manera] a una capa hermana llamada layerA". Luego, cada vez que la capa llamada layerA
se layerA
colocar o layerB
tamaño, layerB
se mueve automáticamente. Es realmente genial, y es justo lo que buscábamos.
Después de un par de días de trabajo, se me ocurrió lo que ahora es CHLayoutManager
. Es básicamente una nueva CAConstraint
de CAConstraint
y amigos, pero para NSViews
. Aquí hay un ejemplo simple de cómo funciona:
CHLayoutConstraint * centerHorizontal = [CHLayoutConstraint constraintWithAttribute:CHLayoutConstraintAttributeMidX relativeTo:@"superview" attribute:CHLayoutConstraintAttributeMidX];
CHLayoutConstraint * centerVertical = [CHLayoutConstraint constraintWithAttribute:CHLayoutConstraintAttributeMidY relativeTo:@"superview" attribute:CHLayoutConstraintAttributeMidY];
[aView addConstraint:centerHorizontal];
[aView addConstraint:centerVertical];
Esto mantendrá aView
centrado en su supervisión, independientemente de cómo se redimensiona la supervisión. Aquí está otro:
[button1 setLayoutName:@"button1"];
[button2 addConstraint:[CHLayoutConstraint constraintWithAttribute:CHLayoutConstraintAttributeMinX relativeTo:@"button1" attribute:CHLayoutConstraintAttributeMaxX]];
[button2 addConstraint:[CHLayoutConstraint constraintWithAttribute:CHLayoutConstraintAttributeMaxY relativeTo:@"button1" attribute:CHLayoutConstraintAttributeMaxY]];
[button2 addConstraint:[CHLayoutConstraint constraintWithAttribute:CHLayoutConstraintAttributeWidth relativeTo:@"button1" attribute:CHLayoutConstraintAttributeWidth]];
Esto mantendrá el button2
anclado en el borde derecho del button1
, así como también button2
la posición y el ancho de Y del button1
al igual que el button1
1.
Internamente, CHLayoutManager
utiliza un NSValueTransformer
para calcular la nueva información de posicionamiento. Algunos de los inicializadores de CHLayoutConstraint
aceptan un NSValueTransformer
, por lo que puede crear manipulaciones de diseño arbitrariamente complejas.
Usamos esto para restringir y diseñar la IU completa, y luego hacer toda la localización en el código (y luego llamar a -sizeToFit
, con algunas modificaciones). Nuestra interfaz de usuario simplemente fluiría en su diseño final. Resultó ser extremadamente conveniente. Simplemente empaquetamos nuestros archivos .strings
, los enviamos a los traductores y luego los colocamos en su lugar cuando los recuperamos, y nuestra aplicación se localizaría instantáneamente para ese idioma.
CHLayoutManager
no es perfecto. No resuelve conflictos, sino que simplemente aplica restricciones en el orden en que se agregan. Por lo tanto, puede restringir (por ejemplo) el MinX
de una vista de 42 maneras diferentes, pero solo se utilizará la última. Además, si restringe el MinX y el MaxX, también se aplicarán en el orden en que se agregaron y no terminarán estirando o reduciendo el ancho. En otras palabras, restringir un atributo de una vista no afectará a los otros atributos. Es compatible con 10.5+ (GC y no). Sin embargo, debido a algunos cambios en Lion, es poco probable que aborde las deficiencias.
A pesar de estas deficiencias, es un marco extremadamente flexible y (IMO) un código bastante ingenioso. (Además, me arruino -[NSView dealloc]
! ¡Yay!)
Actualizar
Ahora que AppKit tiene esta misma funcionalidad (a través de NSLayoutConstraint
), recomiendo usar ese sistema en lugar de CHLayoutManager
. Es mucho más robusto.
Tenga en cuenta que los archivos XIB son simplemente archivos XML en un formato oscuro, por lo que puede traducirlos fácilmente, siempre que pueda encontrar qué cadenas hay para traducir en primer lugar. Por ejemplo, aquí está el fragmento que crea un botón llamado Jenson:
<object class="NSButtonCell" key="NSCell" id="41219959">
<int key="NSCellFlags">67239424</int>
<int key="NSCellFlags2">134217728</int>
<string key="NSContents">Jenson</string>
...
</object>
De modo que puede traducir esa cadena y luego sustituirla en el XIB con su valor traducido. Para verificar que funciona como se espera, puede cambiar el idioma para usar claves aleatorias en su lugar (como BUTTON_TITLE), lo que hará que sea más fácil detectar cuándo falta una.
Sin embargo, las posiciones / tamaños de los elementos son fijos, por lo que puede tener títulos que desbordan el espacio dado en un idioma diferente. Esa es una de las razones por las que las Mac tienen archivos XIB separados para cada idioma, para permitir que los ajustes se realicen idioma por idioma, por difícil que sea mantenerlos.
ACTUALIZACIÓN Enero 2014: el código de "autolayout" de Apple combinado con su localización "Base" tomó la mayoría de mis ideas y las mejoró. Recomiendo no usar mis herramientas antiguas de las que hablo en esta respuesta. Pero, también, el hombre tenía razón!
Recomiendo encarecidamente encarecidamente los cambios de marco en las localizaciones. Sé que esto va en contra del consejo de Apple, pero hay MUCHOS problemas para permitir los cambios de marco: terminas con un billón de casos de borde.
Imagina que tienes 10 XIB en tu aplicación y que soportas 12 idiomas. Tienes 120 diseños diferentes para apoyar, ahora. Simplemente no puedes hacer esto.
Cambia las cuerdas, deja las vistas donde están. Haz que sean más grandes en TODOS los idiomas, si es necesario. Suena como que esto no debería funcionar pero lo hace. (Gané tres Apple Design Awards con una aplicación que está localizada en aproximadamente 10 idiomas de esta manera).
Detalles específicos:
Para la radio y las casillas de verificación, simplemente déjalos que se extiendan hacia la derecha, más allá del último carácter en inglés. Eso también proporciona un área de aterrizaje grande y agradable para los mousers imprecisos.
Para los botones, deben ser anchos de todos modos, porque nunca se ve bien tener el texto abarrotado en el centro de los botones.
Para los títulos en columnas de Tableview, debe auto-dimensionar cuando los cargue, si es necesario.
Para texto explicativo, debe tener un espacio adicional a la derecha, y tal vez una línea adicional. Solo hace que la versión en inglés del XIB parezca menos abarrotada. Claro, los alemanes van a ver un XIB un poco más apretado, pero, hey, son alemanes, probablemente estén acostumbrados a eso. Probablemente hay incluso una palabra alemana para eso. "Deutscheninterfakkenclutterlongen".
Si un campo de texto está centrado, simplemente agregue espacio igual en ambos lados. No hay razón para no hacerlo.
Combiné esto con scripts que absorben todas las cadenas de mis XIB y las puse en archivos .strings, y luego las vuelvo a poner dinámicamente en tiempo de ejecución, para que cualquiera pueda localizar mi aplicación sin herramientas especiales. Simplemente suelta un montón de archivos .strings y ejecútalo.
Publicación del blog que incluye el código fuente completo: [Perdido en traducciones].