11/*
2- * Author: Jianqing Gao
3- * vip@jianqinggao.com
4- * Date: Mar 4, 2021
2+ * Script Author: Jianqing Gao (vip@jianqinggao.com)
3+ * Creation Date: Mar 4, 2021
54 * Description: This document is created for supporting multilanguage sites.
65 */
76//each of this object contains one DOM and one of its possible translation
8- class TranslatableElement
9- {
10- constructor ( e , arr )
11- {
12- this . element = e ;
13- this . languages = arr ;
14- }
15- }
167class MultiLanguage
178{
189 /**
1910 * Construct a default MultiLanguage translator object. Assign default language and
20- * replace all JSONs marked with localized .
11+ * start translationg elements .
2112 * @param {String } defaultLanguage The language that is default to your site and must be available across all elements.
2213 * @param {DOM } select The HTML DOM object of the selector to initalize. Optional.
2314 * @param {String } external The URL to the external JSON sheet
2415 * @param {String } externalJSON The content of external JSON. Note that
2516 * @returns {MultiLanguage } The construsted multilanguage object.
2617 */
27- constructor ( defaultLanguage , externalJSON , select = null )
18+ constructor ( defaultLanguage = "en" , externalJSON = JSON . parse ( "[]" ) , select = null )
2819 {
20+ //The language that is always available to all elements.
2921 this . defaultLang = defaultLanguage ;
22+ //The external sheet in form of a JSONArray
3023 this . externalJSON = externalJSON ;
3124 //an array of doms and their translation
32- //this.localizedArr = [];
3325 this . registeredSelect = [ ] ;
26+ //Check the default language for this user. I
27+ //If there is no record, assign the default language code defined.
3428 this . checkUserLanguage ( ) ;
35- if ( select !== null )
29+ if ( select !== null )
3630 {
3731 this . registerSelect ( select ) ;
3832 }
39-
40- this . translate ( this . externalJSON , this . getUserLanguage ( ) ) ;
33+
34+ this . translate ( this . externalJSON , this . getUserLanguage ( ) ) ;
4135 }
42-
36+
4337 /**
4438 * Add a new select to the listner. This select will also be able to control the global language and follow any changes.
45- * @param {type } select
39+ * @param {Element } select the <code>Element</code> object of the select
4640 * @returns {undefined }
4741 */
4842 registerSelect ( select )
4943 {
50- if ( select !== null && typeof select === "object" )
44+ if ( select !== null && typeof select === "object" && select . tagName === "SELECT" )
5145 {
5246 var l = this . getUserLanguage ( ) ;
5347 this . makeSelect ( select , l ) ;
5448 select . addEventListener ( "change" , ( e ) => {
55- this . translate ( this . externalJSON , select . value ) ;
49+ this . translate ( this . externalJSON , select . value ) ;
5650 //console.log(this);
5751 } ) ;
5852 }
@@ -73,49 +67,89 @@ class MultiLanguage
7367 return false ;
7468 }
7569 /**
76- * Translate all the supported elements to target language
77- * @param {type } target
78- * @returns {undefined }
70+ * Translate all the elements on the translation sheet to target language.This will trigger all registered selects to select the "target" language.
71+ * @param {JSON } json The JSON Array to be read for translation
72+ * @param {type } target The desired language code
73+ * @returns {undefined } None
7974 */
80- translate ( json , target )
75+ translate ( json = this . externalJSON , target )
8176 {
8277 //save language preference
8378 this . setUserLanguage ( target ) ;
8479 //go through all elements
8580 //
86- for ( var i = 0 , max = json . length ; i < max ; i ++ )
81+ ////onsole.log(json.length)
82+ for ( var i = 0 , max = json . length ; i < max ; i ++ )
8783 {
8884 //get the element to be translated
8985 var eleJSON = json [ i ] ;
9086 var ele = document . getElementById ( eleJSON [ "id" ] ) ;
91- if ( ele !== null )
87+
88+
89+ //console.log(ele)
90+ //console.log(eleJSON);
91+ //if the element exists on the page
92+ if ( ele !== null )
9293 {
93- var targetLanguage = eleJSON [ "langs" ] [ target ] ;
94- if ( targetLanguage !== undefined )
95- {
96- this . setElementText ( ele , targetLanguage ) ;
97- } else
98- {
99- this . setElementText ( ele , eleJSON [ "langs" ] [ this . defaultLang ] ) ;
100- }
94+
95+ //get the desired language for the element inner text
96+ var eleJSONLang = eleJSON [ "langs" ] ;
97+ //make sure the langs object for this element exists, if not ,this element does not have innerhtml
98+ if ( eleJSONLang !== undefined )
99+ {
100+
101+ var targetLanguage = this . getTranslatedLanguage ( eleJSONLang , target ) ;
102+ this . setElementText ( ele , targetLanguage ) ;
103+ }
104+
105+ //translate element attribute
106+ var attrJSON = eleJSON [ "attr" ] ;
107+ //see if this element attibute need to be translated.
108+ if ( attrJSON !== undefined )
109+ {
110+ //get what attributes to be translated
111+ var attributes = Object . keys ( attrJSON ) ;
112+ //go through all the attributes need to be translated
113+ for ( var j = 0 , maxj = attributes . length ; j < maxj ; j ++ ) {
114+ //get the attribute to be translated
115+ var key = attributes [ j ] ;
116+ //get the desired language for that attribute
117+ targetLanguage = this . getTranslatedLanguage ( attrJSON [ key ] /*The attribute object itself is a lang json*/ , target ) ;
118+ //Set that attribute to the desired language
119+ this . setElementAttribute ( ele , key , targetLanguage ) ;
120+ }
121+ }
122+
123+
101124 }
125+
102126 }
103127
104- if ( this . registeredSelect . length > 1 )
128+
129+ for ( var j = 0 , max = this . registeredSelect . length ; j < max ; j ++ )
105130 {
106- for ( var i = 0 , max = this . registeredSelect . length ; i < max ; i ++ )
107- {
108- this . makeSelect ( this . registeredSelect [ i ] , target ) ;
109- }
131+ //change selected index
132+ this . makeSelect ( this . registeredSelect [ j ] , target ) ;
110133 }
111134
135+
112136 }
113137
138+ /**
139+ * Determine if the element is a form input element
140+ * @param {type } element The DOM object of that element.
141+ * @returns {Boolean } true of the element id a kind of input or text area, false otherwise.
142+ */
114143 isElementInput ( element )
115144 {
116145 return element . tagName == "TEXTAREA" || element . tagName == "INPUT" ;
117146 }
118147
148+ /**
149+ * Get the innter html of the element. If the elment is input, get the value.
150+ * @param {type } element The DOM object of the element,
151+ * @returns {unresolved } The inner html or valye of the element.
152+ */
119153 getElementText ( element )
120154 {
121155 if ( this . isElementInput ( element ) )
@@ -126,22 +160,67 @@ class MultiLanguage
126160 return element . innerHTML ;
127161 }
128162 }
163+
164+ /**
165+ * Get the desired language of the element. If the desired language doesn't exists,
166+ * use the default language.
167+ * @param {JSONObject } eleJSONLangs The JSONObject formatted "language code":"content", ex. <code>{"cn":"你好","en":"Hello"}</code>
168+ * @param {type } target The target language code. The language you want the element to be translated to. If the one doesn't exists, translate to default language.
169+ * @returns {MultiLanguage.getTranslatedLanguage.eleJSONLangs }
170+ */
171+ getTranslatedLanguage ( eleJSONLangs , target )
172+ {
173+ var targetLanguage = eleJSONLangs [ target ] ;
174+ if ( targetLanguage === undefined )
175+ {
176+ targetLanguage = eleJSONLangs [ this . defaultLang ] ;
177+ }
178+ return targetLanguage ;
179+ }
180+
181+ /**
182+ * Set the appearent text of the element. For non-input elements, it would be the innerHTML property.
183+ * For input elements, it would be "value".
184+ * If you don't wish the UI text of the element to be translated, please leave the "langs" object undefined.
185+ * @param {DOMObject } element The DOM object of the element.
186+ * @param {type } The text to be set.
187+ * @returns {undefined } None.
188+ */
129189 setElementText ( element , text )
130190 {
131191 if ( this . isElementInput ( element ) )
132192 {
133- element . value = text ;
193+ this . setElementAttribute ( element , " value" , text ) ;
134194 } else
135195 {
136196 element . innerHTML = text ;
137197 }
138198 }
139199
200+ /**
201+ * Set the attribute of an element
202+ * @param {type } element The DOM Object of the element.
203+ * @param {type } attributeName The attribute of the element to be changed
204+ * @param {type } text The text to place in.
205+ * @returns {undefined } None
206+ */
207+ setElementAttribute ( element , attributeName , text )
208+ {
209+ element . setAttribute ( attributeName , text ) ;
210+ }
211+
212+ /**
213+ * Get the default user language.
214+ * @returns {DOMString } The user language code in localsorage,
215+ */
140216 getUserLanguage ( )
141217 {
142218 return localStorage . getItem ( "preferred-language" ) ;
143219 }
144-
220+ /**
221+ * Check if the user language exists in the localstorage. If it doesn't exists, assign default language.
222+ * @returns {Boolean }
223+ */
145224 checkUserLanguage ( )
146225 {
147226 var l = this . getUserLanguage ( ) ;
@@ -153,16 +232,26 @@ class MultiLanguage
153232 return true ;
154233 }
155234
235+ /**
236+ * Set the user language.
237+ * @param {type } target The targeted language code to be set.
238+ * @returns {undefined } None
239+ */
156240 setUserLanguage ( target )
157241 {
158242 localStorage . setItem ( "preferred-language" , target ) ;
159243 }
160-
161- addSheet ( json )
244+
245+ /**
246+ * Add an additional sheet to the translator.
247+ * Note that when you add the JSON, it will be concatnated to the original sheet.
248+ * It will also invoke translate method to translate the elements indicated in the new sheet.
249+ * @param {JSONArray } jsonArray JSONArray of the sheet to be added.
250+ * @returns {undefined } None
251+ */
252+ addSheet ( jsonArray )
162253 {
163- this . externalJSON = this . externalJSON . concat ( json ) ;
164-
165- this . translate ( json , this . getUserLanguage ( ) ) ;
254+ this . externalJSON = this . externalJSON . concat ( jsonArray ) ;
255+ this . translate ( jsonArray , this . getUserLanguage ( ) ) ;
166256 }
167257}
168-
0 commit comments