localization - supported - Localizar texto en MvvmCross ViewModels
mvvmcross xamarin forms (2)
Quizás deberías devolver enumeraciones en lugar de cadenas y manejar la localización en las vistas.
Me gustaría obtener todo el texto localizado de ViewModels (ya que a menudo es dinámico), y me preguntaba cómo usaría un convertidor para obtener el texto de los archivos json utilizados para la localización. Por ejemplo, en el siguiente código, me gustaría que LocalisedString use el convertidor que actualmente uso en mis Vistas en los enlaces para texto estático -
public string MyText // used in the binding in the View
{
get
{
string exclamation;
if (MyValue <= 3.3)
{
exclamation = LocalisedString("Rubbish!");
}
else if (OverallScore > 3.3 && OverallScore <= 6.6)
{
exclamation = LocalisedString("Good!");
}
else
{
exclamation = LocalisedString("Excellent!");
}
return exclamation;
}
}
Actualmente usando la versión 1 de MvvmCross.
Cualquier ayuda muy apreciada.
Nota: esta respuesta es sobre vNext - debería ser bastante fácil volver al puerto principal ... Las diferencias en el área no son tan grandes.
Hay un mecanismo de localización de texto integrado en MvvmCross.
La única muestra pública que lo usa es la Muestra de conferencia.
Esta muestra incluye archivos Json específicos compartidos y ViewModel - ver
Cada uno de estos archivos Json contiene pares simples clave-valor como:
{
"Title":"SQLBits X",
"Welcome":"Welcome",
"Sessions":"Sessions",
"Sponsors":"Sponsors",
"Tweets":"Tweets",
"Favorites":"Favorites"
}
Están vinculados a Droid, Touch y WP como contenido o activos ... a los que accede la plataforma mediante el complemento ResourceLoader.
Para usar estos archivos JSON en tiempo de ejecución, el proyecto principal los carga en TextProviderBuilder :
protected override IDictionary<string, string> ResourceFiles
{
get
{
var dictionary = this.GetType()
.Assembly
.GetTypes()
.Where(t => t.Name.EndsWith("ViewModel"))
.Where(t => !t.Name.StartsWith("Base"))
.ToDictionary(t => t.Name, t => t.Name);
dictionary[Constants.Shared] = Constants.Shared;
return dictionary;
}
}
Obviamente, podría cargar fácilmente otros archivos JSON aquí si lo desea. No es raro que algunas de mis aplicaciones tengan:
- un archivo de errores
- un archivo para declaraciones generales compartidas
- un archivo para componentes específicos
- un archivo por ViewModel
Mientras que otros tienen:
- solo un archivo grande!
La internacionalización, cuando está hecha, se realiza cargando un conjunto diferente de archivos JSON. Normalmente, lo que se hace es cargar primero el conjunto predeterminado, luego se cargan las anulaciones incrementales, por lo que puede cargar inglés como predeterminado, Cat como anulación y Cat-Lol como un refinamiento adicional.
Para algunas discusiones sobre esto, vea:
- Localización MvvmCross: cambiar en tiempo de ejecución
- y algunas mejoras futuras - https://github.com/slodge/MvvmCross/issues/55
Suponiendo que tiene un archivo compartido y un archivo por modelo de vista, entonces para proporcionar acceso en tiempo de ejecución a los valores de texto de JSON, BaseViewModel presenta 2 propiedades:
public IMvxLanguageBinder TextSource
{
get { return new MvxLanguageBinder(Constants.GeneralNamespace, GetType().Name); }
}
public IMvxLanguageBinder SharedTextSource
{
get { return new MvxLanguageBinder(Constants.GeneralNamespace, Constants.Shared); }
}
Estas propiedades se usan en el enlace de datos utilizando:
- Ruta que especifica si se debe usar SharedTextSource o TextSource
- MvxLanguageBinderConverter como convertidor
- la tecla de texto como el parámetro convertidor
Por ejemplo, en Droid esto es:
<TextView
style="@style/AboutPageBodyText"
local:MvxBind="{''Text'':{''Path'':''TextSource'',''Converter'':''Language'',''ConverterParameter'':''Title''}}"
/>
Aunque en el moderno encuadernado "suizo" esto se escribiría como:
<TextView
style="@style/AboutPageBodyText"
local:MvxBind="Text TextSource, Converter=Language, ConverterParameter=''Title''"
/>
Cualquier código que desee utilizar el Texto también puede hacerlo: vea, por ejemplo, cómo se crea el texto de TimeAgo a partir de las cadenas de recursos en TimeAgoConverter.cs, que utiliza cadenas de recursos como:
{
"TimeAgo.JustNow":"just now",
"TimeAgo.SecondsAgo":"{0}s ago",
"TimeAgo.MinutesAgo":"{0}m ago",
"TimeAgo.HoursAgo":"{0}h ago",
"TimeAgo.DaysAgo":"{0}d ago",
"TimeAgo.Never":"never"
}
El código para esto es efectivamente:
var valueToFormat = 42;
var whichFormat = "TimeAgo.DaysAgo";
var textProvider = this.GetService<IMvxTextProvider>();
var format = textProvider.GetText(Constants.GeneralNamespace, Constants.Shared, whichFormat);
return string.Format(format, valueToFormat)
El lenguaje Binder y ValueConverter son códigos muy simples
Así que siéntete libre de crear algo más sofisticado para tu aplicación si la necesitas.
Otras técnicas de localización de texto multiplataforma están disponibles. A mí me gustaría probar Vernacular un día. Https://github.com/rdio/vernacular