Inheriting translations? Can this be done?

Topics: Administration, Core, Customizing Orchard, Localization, Writing modules, Writing themes
Jan 23, 2014 at 9:01 AM
When we create an overrided view (cshtml), the translations that are specific for that view (that have the context set to the path of the view) are lost.

We then have to copy over the translations and include them in the module or theme where we override the view.

Is this something that is supposed to work like this? Or can we easily inherit the translations?
Jul 16, 2014 at 2:50 PM
I ran into the same problem, and haven't come up with a elegant solution that wouldn't involve changes in Orchard itself? Maybe it would be a good solution to search for translations in the base class if none are found. But then... when should one stop...
Aug 10, 2014 at 6:24 AM
When we override a template for a shape for example LogOn.cshtml (Model is a shape), Localizer get localization scopes from binding sources and therefore we have inheritance about translation.
But if we override a view template of a controller for example Users/Account/ChallengeEmailSent.cshtml (Model is not a shape), Localizer make scope based on VirtualPath (Orchard.Localization.Text), therefore inheritance does not work in this case.

This is very big problem for me because i must duplicate somethings.
I hope one of coordinators will solves this problem and also this bug: https://orchard.codeplex.com/discussions/560692
Developer
Aug 10, 2014 at 9:22 AM
Can you work around this limitation by creating and rendering a new shape from ChallengeEmailSent.cshtml?
Aug 10, 2014 at 11:55 AM
I don't know how can i create shape from view template? Can you guide me more?
Developer
Aug 10, 2014 at 8:45 PM
Sure. You can create and then render the shape in two steps, like this:
@{
   var myShape = New.MySampleShape(Property1: "some data");
}

@Display(myShape)
Or you can create and render the shape in one step, like this:
@Display.MySampleShape(Property1: "some data")
Make sure you create a Razor view that has the same name as the shape:

MySampleShape.cshtml:
This is a sample shape. Property 1: @Model.Property1
Aug 11, 2014 at 5:55 AM
Thank you for your explanation. I understand how can i create new shape but i cannot understand how this shape can override default template of ChallengeEmailSent.cshtml or .... because it is normal view (Not shape template) for a controller.
In other words i cannot understand how can i solve translation inheritance without duplicating some code or .PO when Model is not a shape.
Localizer get localization scopes from binding sources and therefore we have inheritance about translation only if Model as IShape != null.
Developer
Aug 11, 2014 at 7:53 AM
Yes, so that's why I am suggesting that perhaps you can override the ChallengeEmailSent.cshtml view in your theme (or module even) and refactor out all of its contents to a shape. This shape will now render your localized strings. You would have to duplicate the default strings if you use those, so it's still not perfect, but maybe a little better. Feel free to create an issue for this subject as well.
Aug 11, 2014 at 9:13 PM
A slightly less 'not-perfect' solution would be to edit src\Orchard\Localization\Services\DefaultLocalizedStringManager.cs file or better yet implement your own ILocalizedStringManager (I recommend this solution) and supress this dependency.
You can copy the implementation of ILocalizedStringManager from DefaultLocalizedStringManager and only change this method
public string GetLocalizedString(string scope, string text, string cultureName) {
            var culture = LoadCulture(cultureName);

            string scopedKey = (scope + "|" + text).ToLowerInvariant();
            if (culture.Translations.ContainsKey(scopedKey)) {
                return culture.Translations[scopedKey];
            }

            string genericKey = ("|" + text).ToLowerInvariant();
            if (culture.Translations.ContainsKey(genericKey)) {
                return culture.Translations[genericKey];
            }

            // Appended code to handle inherited translations
            var any = culture.Translations.Keys.Where(t => t.EndsWith(genericKey)).ToList();
            if (any.Any())
            {
                return culture.Translations[any[0]];
            }

            return GetParentTranslation(scope, text, cultureName);
        }
The appended code looks for any matching translation, whatever the scope (scope is you translation class name).
This works, without the need to duplicate translations for derived classes, though there is a possibility, than the wrong translation might be served ie.: consider an english word that might be translated into two different words depending on the context.

But for your case this, will work just fine :)
Aug 12, 2014 at 4:50 AM
@sfmskywalker, Thank you for your comment. I will try that. Also i created an issue for this.
@SzymonS, Thanks a lot. I will try your solution too. It can be a workaround for now.

I hope this problem will be solved as soon permanently.