I18N-Portable icon indicating copy to clipboard operation
I18N-Portable copied to clipboard

Strategy for updating locale files

Open jemunk opened this issue 6 years ago • 15 comments

First of all... Thanks for a simple and easy to use translation plugin! My question is: Is it possible to update the local files while running the app?

Is see these issues:

  • Can the locale files be overridden? Does Android and iOS allow this?
  • Does I18NPortable needs to be reinitialized and is reinitialization supported?

jemunk avatar Nov 02 '18 09:11 jemunk

There´s no way to do this at the moment. I had some ideas in the past for a similar thing but I gave up, given the complexity of it. What´s the use case?

xleon avatar Nov 02 '18 17:11 xleon

The use case is to very swiftly distribute new translations instead of making a new release of the app every time. Please elaborate.... what complexities are you aware of?

jemunk avatar Nov 02 '18 22:11 jemunk

Ok, that´s the exact use case I thought about time ago. It would be very handy right? The question though is how many users of this library would benefit from such feature. You are the first to ask :)

About complexity:

The library loads embedded files in the application package. They can´t be modified. My original idea was to copy all locales to the local storage at application startup. Indeed, those files can be modified/updated but it adds complexity because we still have to "maintain" 2 copies of the locales, and keep them in sync:

  • What if you updated from remote source and then you update your embedded copy?
  • How do you resolve conflicts between local and remote versions?

The second problem is about the strategy of updating your local stuff from a remote source. It could be done by providing an async loading mechanism as an interface that a developer could implement to load remote files the way he/she wants, and perhaps a public method UpdateLocales() that a developer could chose to call when appropriate in their app live-cycle.

All of this can be done, and it would be super cool, but the library goal was always to stay simple and it maybe out of the scope for the majority of users.

xleon avatar Nov 03 '18 00:11 xleon

Thank you for your answer.

So basically, the update of the locale files could be handed away to user of the library. So all the library has to offer is:

  1. An updated SetResourcesFolder() allowing to give a path to a writable area.
  2. Add UpdateLocales() method for re-parsing the local files. Could also be omitted and just wait for the next app session.

I don't know. But maybe I'll do a fork and try implementing, that is, if you don't fell for it.

jemunk avatar Nov 05 '18 11:11 jemunk

Seams to me that it would need a deeper refactoring. For instance, loading locales or initializing the library would be async now. That´s a breaking change.

xleon avatar Nov 06 '18 09:11 xleon

Hi @jemunk I´m reworking the whole library, simplifying code and improving scalability, but keeping it as simple as possible.

Regarding custom/updated locale files, as you suggested I think the best approach would be delegating responsibility on the library user, so this is my idea:

You can now provide an ILocaleLoader object:

public interface ILocaleLoader
{
    Dictionary<string, string> Load(string locale, string resource);
}

Note: The reason to have string resource is that I´m adding support for multiple locale files.

The library will simple load a locale from your interface implementation. Updating locales from any other source (ie: remote url) is completely up to you, which means that the library does not need to know if you updated them or when you did it.

If we found out a reusable strategy to load remote locales, that would come in a separate plugin, keeping this library to a minimum.

Thoughts?

xleon avatar Nov 17 '18 23:11 xleon

It definitely sound usable. For the purpose of reading a file, its fine not having it async. And if needed to have that file updated from a server, it could be made in a separate thread preparing it, for the next app session. I can't think of a case where the Load delegate should fetch from a server, as most apps should be somehow available for offline usage.

jemunk avatar Nov 19 '18 09:11 jemunk

Actually, the implementation I´m doing at the moment will allow you to refresh loaded translations in real time. You will be able to trigger it as soon as you make the updates from server.

xleon avatar Nov 19 '18 12:11 xleon

Sounds very promising 👍

jemunk avatar Nov 19 '18 12:11 jemunk

I´m basically decoupling the loader from the rest of the code. I will provide a default one, but a developer could make his own.

Btw, what format will you be using on your remote locales? key value pairs or any other?

xleon avatar Nov 19 '18 12:11 xleon

They are currently stored in a remote SQL database. But will probably be transferred to the app as JSON as an object containing key/value. But we haven't decided yet.

jemunk avatar Nov 19 '18 12:11 jemunk

In that case it would make sense to save json files to FileSystem and use something like https://github.com/xleon/I18N-Portable/blob/master/I18NPortable.JsonReader/JsonKvpReader.cs on your ILocaleLoader

xleon avatar Nov 19 '18 12:11 xleon

Sure! Something like that, I have in mind.

jemunk avatar Nov 19 '18 12:11 jemunk

We have to switch framework because of this. The client wants to be able to edit the texts externally. We will download updates to the texts runtime. Just to say, there is more than one person that needs it.

JanettHolst290490 avatar Apr 22 '21 15:04 JanettHolst290490

Just found this discussion. I would need to load a locale file from some location in the filesystem, not the embedded resources, so that a user can modify it or receive a modifed file from me, without updating the whole app, only restart it. I don't see how an ILocaleLoader is used by the library and how I have to tell the library to use an implementation by me. What do the parameters represent? Thanks for any info!

AnnekeHeelsum avatar Jul 29 '21 09:07 AnnekeHeelsum