2018年6月14日 星期四

[Vue] Custom plugin for getting i18n data with vue-i18n (2)


  Vue.js    vue-i18n     Plugins 


Introduction


In previous article, [Vue] Custom plugin for getting i18n data with vue-i18n (1), we created a plugin to make vue-i18n get the backend’s i18n json data.
In this tutorial, we will improve the plugin to support getting multiple i18n data from backend with keys. For example, the plugin will send a HttpGet request to

http://xxxxx/api/i18n/Get?lang=en-US&keys=key1,key2,key3

which will get the following response data:


{"key1": {"A":"Hello", "B":"world"}, "key2": {"C":"Vue.js", "D":"is awesome"}}




Environment


vue.js 2.5.13
vue-i18n 7.4.2
ASP.NET Web API 2



Implement


Update Web API to support multiple keys response

We had an ASP.NET Web API action for responding the i18n json data in this article: [Vue] Internationalization with vue-i18n

Let’s modify it to make it support multiple keys query.

[HttpGet]
[Route("api/i18n/Get")]
public async Task<HttpResponseMessage> Get(string keys, string lang)
{
            CultureInfo ci = new CultureInfo(lang);

            var keyArr = keys.Split(',');
            dynamic expando = new ExpandoObject();
           
            foreach (string key in keyArr)
            {
                var resource = ResourceFactory.GetResource(key, ci); //Get the key-value pairs as Dictionary<string, string>
                addProperty(expando, key, resource);
            }

            string json = JsonFactory.SerializeObjectToCamelJson(expando);
            var response = this.Request.CreateResponse(HttpStatusCode.OK);
            response.Content = new StringContent(json, Encoding.UTF8, "application/json");
            return response;
        }

        private void addProperty(ExpandoObject expando, string propertyName, object propertyValue)
        {
            // ExpandoObject supports IDictionary so we can extend it like this
            var expandoDict = expando as IDictionary<string, object>;
            if (expandoDict.ContainsKey(propertyName))
                expandoDict[propertyName] = propertyValue;
            else
                expandoDict.Add(propertyName, propertyValue);
}

Here we use ExpandoObject to create a dynamic object since Web API don’t know what keys will be sent.
(Reference: [C#] ExpandoObject)




Modify the Vue plugin

All we have to do is make the plugin read the keys from the Vue instance’s property and send the request with keys.

JS (plugin)

Take a look at the modified part of the plugin.

Vue.mixin({
            created: function () {
                if (this.i18nKey) {
                    let keys = this.i18nKey;
                    let getEnUS = this.getI18n(keys, 'en-US');
                    let getZhTW = this.getI18n(keys, 'zh-TW');
                    let getZhCN = this.getI18n(keys, 'zh-CN');

                    this.$i18nPromise = axios.all([getEnUS, getZhTW, getZhCN])
                        .then(axios.spread(function (response1, response2, response3) {
                            i18n.setLocaleMessage('enUS', response1.data);
                            i18n.setLocaleMessage('zhTW', response2.data);
                            i18n.setLocaleMessage('zhCN', response3.data);
                            i18n.locale = Vue.prototype.$locale;
                        }));
                }
            }
)

We get the keys from this.i18nKeys, which will be set in the Vue instance, and getI18n(keys, 'en-US') will send the request like http://xxxxx/api/i18n/Get?lang=en-US&keys=key1,key2,key3

A full version is as following,

Vue.use(VueI18n);

// Create VueI18n instance with options
const i18n = new VueI18n({
    locale: '', // set locale
    fallbackLocale: 'zhTW',
});

const serverUrl = "http://xxxx/api/i18n/Get";

var MyPlugin = {
    install: function (Vue, options) {

        //If Vue instance use i18n data immediately, such as in created, mounted, then you have to use this promise
        Vue.prototype.$i18nPromise = null;

        /* Instance method */
        Vue.prototype.getI18n = function (keys, lang) {
let uri = serverUrl.concat("?lang=", lang, "&keys=" , keys);
            return axios.get(uri);
        }

        // Vue.mixin() for injecting functionality into all components.
        Vue.mixin({
            created: function () {
                if (this.i18nKeys) {
                    let keys = this.i18nKeys;
                    let getEnUS = this.getI18n(keys, 'en-US');
                    let getZhTW = this.getI18n(keys, 'zh-TW');
                    let getZhCN = this.getI18n(keys, 'zh-CN');

                    this.$i18nPromise = axios.all([getEnUS, getZhTW, getZhCN])
                        .then(axios.spread(function (response1, response2, response3) {
                            i18n.setLocaleMessage('enUS', response1.data);
                            i18n.setLocaleMessage('zhTW', response2.data);
                            i18n.setLocaleMessage('zhCN', response3.data);
                            i18n.locale = Vue.prototype.$locale;
                        }));
                }
            },
            methods: {
               
            }

           
        });
    }
};



Use the plugin

Now we can use the plugin in the Vue instance like this,



Vue.use(MyPlugin);

var app = new Vue({
    el: '#app',
    i18n: i18n,
    data: {
        //Load i18n
        i18nKeys: 'Key1, Key2, Key3',
    },
    methods: {
    },
    created: function () {
        this.locale = 'zhTW';
    },
})





Reference




沒有留言:

張貼留言