Base solution for your next web application
Open Closed

need help extending default localization resources #6731


User avatar
0
alexanderpilhar created

6.8.0, Angular, .NET Framework

Is it possible to extend default localization resources like described here?: Extending Localization Sources

I'm asking because I get the following error when I try to do so:

FATAL 2019-03-29 13:39:47,595 [1    ] Abp.AbpBootstrapper                      - Abp.AbpInitializationException: ProjectName source contains more than one dictionary for the culture: en
   bei Abp.Localization.Dictionaries.Xml.XmlEmbeddedFileLocalizationDictionaryProvider.Initialize(String sourceName)
   bei Abp.Localization.MultiTenantLocalizationSource.Initialize(ILocalizationConfiguration configuration, IIocResolver iocResolver)
   bei Abp.Localization.LocalizationManager.InitializeSources()
   bei Abp.AbpKernelModule.PostInitialize()
   bei System.Collections.Generic.List`1.ForEach(Action`1 action)
   bei Abp.AbpBootstrapper.Initialize()
Abp.AbpInitializationException: ProjectName source contains more than one dictionary for the culture: en
   bei Abp.Localization.Dictionaries.Xml.XmlEmbeddedFileLocalizationDictionaryProvider.Initialize(String sourceName)
   bei Abp.Localization.MultiTenantLocalizationSource.Initialize(ILocalizationConfiguration configuration, IIocResolver iocResolver)
   bei Abp.Localization.LocalizationManager.InitializeSources()
   bei Abp.AbpKernelModule.PostInitialize()
   bei System.Collections.Generic.List`1.ForEach(Action`1 action)
   bei Abp.AbpBootstrapper.Initialize()
FATAL 2019-03-29 13:39:47,700 [1    ] soft.AspNetCore.Hosting.Internal.WebHost - Application startup exception
Abp.AbpInitializationException: ProjectName source contains more than one dictionary for the culture: en
   bei Abp.Localization.Dictionaries.Xml.XmlEmbeddedFileLocalizationDictionaryProvider.Initialize(String sourceName)
   bei Abp.Localization.MultiTenantLocalizationSource.Initialize(ILocalizationConfiguration configuration, IIocResolver iocResolver)
   bei Abp.Localization.LocalizationManager.InitializeSources()
   bei Abp.AbpKernelModule.PostInitialize()
   bei System.Collections.Generic.List`1.ForEach(Action`1 action)
   bei Abp.AbpBootstrapper.Initialize()
   bei Abp.AspNetCore.AbpApplicationBuilderExtensions.InitializeAbp(IApplicationBuilder app)
   bei Abp.AspNetCore.AbpApplicationBuilderExtensions.UseAbp(IApplicationBuilder app, Action`1 optionsAction)
   bei CompanyName.ProjectName.Web.Startup.Startup.Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)

My folder structure for localization resources looks like this:

  • Localization
    • ProjectName
      • ProjectName.xml
      • ProjectName-xx.xml
      • ...
    • ProjectNameExtended.xml
      • ProjectName.xml
      • ProjectName-xx.xml
      • ...

ProjectNameLocalizationConfigurer.cs looks like this:

public static void Configure(ILocalizationConfiguration localizationConfiguration)
{
    localizationConfiguration.Sources.Add(
        new DictionaryBasedLocalizationSource(
            ProjectNameConsts.LocalizationSourceName,
            new XmlEmbeddedFileLocalizationDictionaryProvider(
                typeof(ProjectNameLocalizationConfigurer).GetAssembly(),
                "CompanyName.ProjectName.Localization.ProjectName"
            )
        )
    );

    localizationConfiguration.Sources.Extensions.Add(
        new LocalizationSourceExtensionInfo(
            "(ProjectName",
            new XmlEmbeddedFileLocalizationDictionaryProvider(
                typeof(ProjectNameLocalizationConfigurer).GetAssembly(),
                "CompanyName.ProjectName.Localization.ProjectNameExtended"
            )
        )
    );
}

Please, advise!

EDIT: Removed project name from code-block


27 Answer(s)
  • User Avatar
    0
    aaron created
    Support Team

    Abp.AbpInitializationException: ProjectName source contains more than one dictionary for the culture: en

    Check the culture specified in the files.

  • User Avatar
    0
    geertveenstra created

    Aaron, really helpful comment ... I would expect a more elaborate answer from support guys

    @alexanderpilhar This should work (I had a hard time finding a solution some tome ago, documentation is not really clear on this):

    Localization ProjectName ProjectName.xml ProjectName-xx.xml ... Extended ProjectName.xml ProjectName-xx.xml ...

    public static void Configure(ILocalizationConfiguration localizationConfiguration)
    {
        localizationConfiguration.Sources.Add(
            new DictionaryBasedLocalizationSource(
                ProjectNameConsts.LocalizationSourceName,
                new XmlEmbeddedFileLocalizationDictionaryProvider(
                    typeof(PoinowLocalizationConfigurer).GetAssembly(),
                    "CompanyName.ProjectName.Localization.ProjectName"
                )
            )
        );
    
        localizationConfiguration.Sources.Extensions.Add(
            new LocalizationSourceExtensionInfo(
                ProjectNameConsts.LocalizationSourceName,
                new XmlEmbeddedFileLocalizationDictionaryProvider(
                    typeof(PoinowLocalizationConfigurer).GetAssembly(),
                    "CompanyName.ProjectName.Localization.Extended"
                )
            )
        );
    }
    
  • User Avatar
    0
    alexanderpilhar created

    @aaron as far as I understand linked documentation, the culture specified in the files should be okay - I'm trying to extend CompanyName.ProjectName.Localization.ProjectName.ProjectName.xml (which is culture="en") with CompanyName.ProjectName.Localization.ProjectNameExtended.ProjectName.xml (which is culture="en" as well).

    @geertveenstra did you mean to move all default localization files from CompanyName.ProjectName.Localization.ProjectName to CompanyName.ProjectName.Localization? And the rootNamespace: "CompanyName.ProjectName.Localization.ProjectName" for XmlEmbeddedFileLocalizationDictionaryProvider still works?

  • User Avatar
    0
    aaron created
    Support Team

    Check the culture specified in the files in the ProjectNameExtended folder.

  • User Avatar
    1
    geertveenstra created

    @alexanderpilhar,

    Sorry, the indentation was not good.

    This would be the structure of the directories:

    • Localization
      • ProjectName (this is your projectname where the original aspnetzero localization files are)
        • ProjectName.xml (for english (en))
        • ProjectName-de.xml (for german (de))
        • ProjectName-nl.xml (for dutch (nl))
        • ...
      • Extended (this is your new extension directory where your added/changed localization keys are)
        • ProjectName.xml (for english (en))
        • ProjectName-de.xml (for german (de))
        • ProjectName-nl.xml (for dutch (nl))
        • ...

    The problem is the extension directory can apparently not have the name starting with ProjectName (e.g. ProjectNameExtended), somehow that will not work) so just give it another name.

  • User Avatar
    0
    maliming created
    Support Team

    This is my practice, for reference. AbpWeb-zh-Hans.json

    {
      "culture": "zh-Hans",
      "texts": {
        "InternalServerError": "服务器内部错误,请重试!",
        "ValidationError": "请求发生错误!",
        "ValidationNarrativeTitle": "传入的参数有错误,请检查!"
      }
    }
    

  • User Avatar
    0
    alexanderpilhar created

    @aaron here are the cultures specified in ProjectNameExtended folder:

    • ProjectName.xml: culture="en"
    • ProjectName-de.xml: culture="de"

    @geertveenstra I see. I did as you described but now my resource extension files cannot be found at all ... Note: I did make sure to set build-process to embedded resource for the files. I also checked namespace for errors.

    @maliming thanks for your comment! I think I'm falling in love with the json resource files :D They seem to be much more readable!

  • User Avatar
    0
    alexanderpilhar created

    Maybe I'm all wrong about the rootNamespace?

    Documentation says (Registering XML Localization Sources):

    XmlEmbeddedFileLocalizationDictionaryProvider gets an assembly containing XML files (GetExecutingAssembly simply refers to current assembly) and a namespace of XML files (namespace is the calculated assembly name + folder hierarchy of XML files).

    And this is XmlEmbeddedFileLocalizationDictionaryProvider.cs

    @geertveenstra this line explains why extension directory name cannot start with ProjectName.

    So, it seems my original problem was caused by the resource extension folder name starting with ProjectName. Now that I have renamed this folder from ProjectNameExtended to Extended, resource extension files don't seem to have any effect at all.

    This is what Logs.txt says:

    WARN  2019-04-02 10:30:54,713 [4    ] naries.DictionaryBasedLocalizationSource - Can not find 'Text.Name' in localization source 'ProjectName'!
    ...
    (and some more of the same)
    
  • User Avatar
    0
    maliming created
    Support Team

    @alexanderpilhar If I use a template project(https://github.com/aspnetboilerplate/module-zero-core-template) to show you the extension's built-in localization, what do you think?

  • User Avatar
    0
    alexanderpilhar created

    @maliming that would be great : )

  • User Avatar
    0
    maliming created
    Support Team

    https://github.com/maliming/abplocalization/blob/master/src/QA.Web.Mvc/Controllers/HomeController.cs#L17

    https://github.com/maliming/abplocalization/blob/master/src/QA.Core/Localization/SourceFiles/Abp/Abp.xml#L4

    https://github.com/maliming/abplocalization/blob/master/src/QA.Core/Localization/QALocalizationConfigurer.cs#L23

    Access this url: http://localhost:62114/home/test

    {
        "result": null,
        "targetUrl": null,
        "success": false,
        "error": {
            "code": 0,
            "message": "Hello You Need Login!",
            "details": null,
            "validationErrors": null
        },
        "unAuthorizedRequest": true,
        "__abp": true
    }
    
  • User Avatar
    0
    alexanderpilhar created

    @maliming thank you for the provided example!

    I see you are extending Abp localization resource files. In my case, I'm trying to extend QA localization resource files - which I cannot make work.

    Basically, what I'm trying to do is to split the localization resource files that come with ASPNETZERO into multiple files depending on context. But that's just a nice-to-have and not a must-have. So, for now I will give up on this and continue putting all my text-elements in the single resource file.

    Nevertheless, thanks for your time and help @all!

  • User Avatar
    1
    geertveenstra created

    Basically, what I'm trying to do is to split the localization resource files that come with ASPNETZERO into multiple files depending on context.

    That is exactly what I did ... Working fine here (but like I mentioned, it only works when your Extension folder names do not start with your Project folder name). Don't know how to explain it further.

  • User Avatar
    0
    alexanderpilhar created

    @geertveenstra the answer you provided looks really promising to me and I really think it is correct. I don't know why localization won't be applied when I implement it your way (there might be something I'm still missing) - I might give it a try another time or I might try to implement it in a fresh project. Anyway, as soon as I get it to work with the solution you provided, I will mark your answer as the correct one!

  • User Avatar
    0
    FlexSolution created

    We are using the .net Core + Angular version 6.9.1 and I wanted to do the same. I wanted to have several xml files so I could organize the translations more clearly.

    I have the same problem. No matter what I do, the additional files are ignored. It only takes the translation from the main file.

  • User Avatar
    0
    FlexSolution created

    @alexanderpilhar did you find the bug? None of the combinations work for me.

  • User Avatar
    0
    alexanderpilhar created

    @FlexSolution unfortunately no, not yet. I will try again using a clean project as soon as I find the time to do so.

  • User Avatar
    0
    FlexSolution created

    I downloaded a completely clean project today. Combination .Net-Core and Angular, version 6.9.1

    It just doesn't work.

    Maybe someone from support can just download our project and try to add more language files in another folder?

    @alexanderpilhar Maybe you will open this request here again so that I don't create a new one unnecessarily although it is the same topic?

  • User Avatar
    0
    alexanderpilhar created

    Reopening as requested by @FlexSolution.

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi @FlexSolution

    If you can send your solutşon to [email protected], we can take a look.

    thanks,

  • User Avatar
    0
    FlexSolution created

    I sent you everything. Maybe I'm missing something. But there are also no error messages.

    I'm curious to see where the error is.

  • User Avatar
    0
    FlexSolution created

    I sent the mail a week ago and haven't received any feedback yet. Can you confirm if the mail arrived at all?

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi @FlexSolution

    Sorry, the email was in spam foldr, I just saw it. We are checking it.

  • User Avatar
    1
    ismcagdas created
    Support Team

    Hi again,

    I tested your project and changing the xml file name from 'abc.xml' to 'FlexSped.xml' and using beloc code block in FlexSpedLocalizationConfigurer.cs worked. Could you also try that ?

    localizationConfiguration.Sources.Extensions.Add( new LocalizationSourceExtensionInfo( "FlexSped", new XmlEmbeddedFileLocalizationDictionaryProvider( typeof(FlexSpedLocalizationConfigurer).GetAssembly(), "FlexSped.Localization.Second" ) ) );

  • User Avatar
    0
    FlexSolution created

    So it is not possible to name the XML file the way you want, just the folder?

    I also tried this: localizationConfiguration.Sources.Add( new DictionaryBasedLocalizationSource("Group2", new XmlEmbeddedFileLocalizationDictionaryProvider( typeof(FlexSpedLocalizationConfigurer).GetAssembly(), "FlexSped.Localization.Group2" ) ) ); to insert a new source instead of extending the existing one.

    The only way it works is to extend the existing ones and give each XML file the same name?

  • User Avatar
    1
    ryancyq created
    Support Team

    yes, localization extension only works for localization files with the same name.

  • User Avatar
    0
    michael.pear created

    This was an extremely confusing post to address the issue of extending a localization source, which allows overriding existing entries and adding new ones. I wanted to organize things so that what I add for my application is separate from the AspNetZero supplied language files. To summarize the solution, you need to do the following assuming a project "YourProject" is the project that is provided from AspNetZero:

    1. In folder YourProject.Core/Localization, you find a YourProject folder with language files prefixed with "YourProject" (e.g. YourProject.xml, YourProject-de.xml, etc.
    2. You need to add a folder under YourProject.Core/Localization with a different name like "ExtendYourProject".
    3. In the new Folder, for any languages you want to extend, add a file with the SAME name as the language file you are extending (e.g., YourProject-de.xml). The file will contain any entries you want to override and any new entries.
    4. In the language configurer in YourProject.Core/Localization file YourProjectLocalizationConfigurer add the code:
                localizationConfiguration.Sources.Extensions.Add(
                    new LocalizationSourceExtensionInfo("YourProject",
                        new XmlEmbeddedFileLocalizationDictionaryProvider(
                            typeof(YourProjectLocalizationConfigurer).GetAssembly(),
                            "YourProject.Localization.ExtendYourProject"
                        )
                     )
                );
               
    

    Rebuild, and you should find that the extensions are now used. You do need to make sure that the "build action" for any files you add are showing "Embedded Resource". Any XML files that I added seem to be given that automatically in visual studio.

    Hope that helps makes sense of a rather long involved post for something relatively simple in the end.