Hi
I have followed the localisation guide here: https://docs.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/localization/text?tabs=windows
If I include my AppResources.resx within my forms project, XAML picks up the translations just fine, but this is NOT how I wish to proceed.
I wish to have the translations in a separate project, currently a .net2.0 library MyApp.Shared.Resources this project contains only the AppResources.resx file in the project root together with the associated AppResources.Designer.cs
I have changed the CustomTool field to PublicResXFileCodeGenerator as per the documentation.
The error I see is:
System.Exception: 'Could not find any resources appropriate for the specified culture or the neutral culture. Make sure "ProteusPatientApp.Shared.Resources.AppResources.resources" was correctly embedded or linked into assembly "ProteusPatientApp" at compile time, or that all the satellite assemblies required are loadable and fully signed.'
In my forms project, I have the required extension thus:
using MyApp.Shared.Interfaces;
using System;
using System.Globalization;
using System.Reflection;
using System.Resources;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace MyApp.Helpers
{
// You exclude the 'Extension' suffix when using in XAML
[ContentProperty("Text")]
public class TranslateExtension : IMarkupExtension
{
// You exclude the 'Extension' suffix when using in XAML
readonly CultureInfo ci = null;
const string ResourceId = "MyApp.Shared.Resources.AppResources";
static readonly Lazy<ResourceManager> ResMgr = new Lazy<ResourceManager>(() => new ResourceManager(ResourceId, IntrospectionExtensions.GetTypeInfo(typeof(TranslateExtension)).Assembly));
public string Text { get; set; }
public TranslateExtension()
{
if (Device.RuntimePlatform == Device.iOS || Device.RuntimePlatform == Device.Android)
{
ci = DependencyService.Get<ILocalize>().GetCurrentCultureInfo();
}
}
public object ProvideValue(IServiceProvider serviceProvider)
{
if (Text == null)
return string.Empty;
var translation = ResMgr.Value.GetString(Text, ci);
if (translation == null)
{
#if DEBUG
throw new ArgumentException(
string.Format("Key '{0}' was not found in resources '{1}' for culture '{2}'.", Text, ResourceId, ci.Name),
"Text");
#else
translation = Text; // HACK: returns the key, which GETS DISPLAYED TO THE USER
#endif
}
return translation;
}
}
}
In my XAML, I have:
xmlns:helpers="clr-namespace:ProteusPatientApp.Helpers;assembly=ProteusPatientApp"
<Label Text="{helpers:Translate CompletedPatientEvents}" Margin="0,5,0,10" FontSize="25" TextColor="{StaticResource SL_DarkBlue}" FontAttributes="Bold" HorizontalOptions="Center" VerticalOptions="Start"/>
I don't believe I am doing anything wrong - eg I am following the guide. My only route if I cannot share resources between projects is to roll my own resources manager, or duplicate the resources across every project that requires them. Both are a bit of a wind up!
If I plonk this code:
var assembly = typeof(Shared.Resources.AppResources).GetTypeInfo().Assembly; // "EmbeddedImages" should be a class in your app
foreach (var res in assembly.GetManifestResourceNames())
{
System.Diagnostics.Debug.WriteLine("found resource: " + res);
}
Into App.xaml.cs constructor, I see output:
Found resource: "ProteusPatientApp.Shared.Resources.AppResources.resources"
EG, the XAML code can see the project that contains my resources just fine.
Anyone got any idea's how to resolve?