EmberJS : Translation using i18n library is not working? - javascript

My project need to support 3 different languages. We used Emberjs for development.
So for implementation of translation , I followed the tutorial provided in the following URL
http://eviltrout.com/2013/11/24/i18n-in-ember.html
I have included the i18n.js from the following url
https://github.com/fnando/i18n-js/blob/master/vendor/assets/javascripts/i18n.js
into my project Then i created a file named translation.js with contents of
I18n.translations = {
en: {
savingquote: 'savings made simple'
},
hi: {
savingquote: 'बचत सरल बनाया'
},
es : {
savingquote:'ahorros de forma sencilla'
}
};
And in my project am view page am referring it as {{i18n savingquote}} . And added a helper to my app.js with following code
Ember.Handlebars.registerHelper('i18n', function(property, options) {
var params = options.hash,
self = this;
// Support variable interpolation for our string
Object.keys(params).forEach(function (key) {
params[key] = Em.Handlebars.get(self, params[key], options);
});
return I18n.t(property, params);
});
Now my requirement is to change language of my project without reloading . So in my language change function am adding I18n.locale = 'hi'; . But handlebars appearing in default language english.
Your comments are welcome.

I think it is not necessary to reload the page but you will need to refresh/rerender the active ember view since translations are not meant to be bound properties.
DISCLAIMER: have not used the specific implementation, but have implemented a similar functionality supporting ember apps (in code and templates) and html parts (out of templates).

Related

JavaScript - Front-end MVC

My actual question here:
I'm wondering if (beargrylls.com) uses Django or it's packages. Or some other framework. Or a custom framework? Also, if you take a look at the website (beargrylls.com), you can see that it uses a lot of paralax scrolling, sliders and cool animations. Is this custom-made or is this another framework/plugin/whatever?
If found an awesome website (beargrylls.com) on awwwards.com. I'm familiar with the MVC model that Laravel uses. So I know the basics. But I found out that (beargrylls.com) uses some kind of routing inside it's scripts!?
What I also found remarkanble is that the script(s) and the entite css of the website is loaded in inline HTML. So there are no HTTP requests, no files to load except the images
Which framework/plugin compiles this?
Example:
, Route = function t() {
classCallCheck(this, t);
var e = new Router({
xhr: !0
});
e.get("/", HomeController),
e.get("/about", AboutController),
e.get("/television", TelevisionController),
e.get("/live", LiveController),
e.get("/experiences", ExperiencesController),
e.get("/socialwall", SocialwallController),
e.get("/adventurers", AdventurersController),
e.get("/termsofuse", TermsofuseController),
e.get("/faqs", FaqsController),
e.get("/signup", SignupController),
e.error(ErrorController),
e.run()
}
, App = function t() {
classCallCheck(this, t),
Support.init(),
index.TopWhenRefresh(),
new Route
};
new App;
Another example that boosted my suspisions can be found inside it's createClass function or class. Where it assumably creates classes.
this.backgroundWrap = index.Geb.id("h-header-background-wrap"),
this.centerWrap = index.Geb.id("h-header-center-wrap"),
this.foregroundWrap = index.Geb.id("h-header-foreground-wrap"),
this.titleWrap = index.Geb.id("h-header-title-wrap"),
this.introTxt = index.Geb.id("h-intro-txt"),
this.introLine = index.Geb.id("h-intro-line"),
this.introVideo = index.Geb.id("h-intro-video"),
this.introScroll = index.Geb.id("h-intro-scroll"),
this.nav = index.Geb.class("nav")[0],
this.progress = index.Geb.id("h-intro-progress"),
this.scrollLineWrap = index.Geb.id("h-header-scroll-line-wrap"),
this.scrollTxtWrap = index.Geb.id("h-header-scroll-txt-wrap"),
this.stickyBurger = index.Geb.id("sticky-burger"),
So it seems to me that almost this entire website (routing, element classes and more) is created trough this script. I even see some mailchimp tags here.
I looked into the Django framework because of some of the links to media folders like /static/.
Penryn-starter
A starter kit for web development.
Docker
Browsersync
PHP 7.1.8
PostCSS
Css Nano
ES2015
ESLint
Rollup
Uglify JS 3
Skylake
https://github.com/ariiiman/penryn-starter
Skylake:
It's a Light JavaScript library named Skylake:
https://github.com/ariiiman/skylake
example:
const animation = new S.Merom('.element', '3dy', 0, 100, 1000, 'Power4InOut')
animation.play()
animation.reverse()
Similar functions can also be found in the Sources tab of the Google Devtools on beargrylls.com:
this.tlImg.from(this.background, "3dy", 10, 0, 2e3, "ExpoOut")
Also, in the script can skylake be found litterally:
scroll: {
throttle: !0,
skylake: "Scroll"
},
But I'm not quite sure what this actually does. I can't explain the routing class or anything of that sort. But it defenitely uses this Skylake library.
The same structure of code can be found on these websites: https://www.aristidebenoist.com/ (author of Skylake) and on http://www.jennyjohannesson.com/
though I do not think that these websites are using Skylake. Or just use other variables or something. But this:
, App = function e() {
classCallCheck(this, e),
Support.init(),
index.TopWhenRefresh(),
new Router({
xhr: !0
})
};
!function(e) {
new App
}();
}
)();
is exactly the same as on beargrylls.com
also the almost exact same Route class can be found on http://www.jennyjohannesson.com/

Javascript code organization data driven application

I'm currently working on the front-end of a medium/large-scale data-driven Asp.net MVC application and I have some doubts about the right code-organization/design pattern to follow.
The web application is made by multiple pages containing many Kendo UI MVC widgets defined with Razor template.
For those who are unfamiliar with Kendo, the razor syntax is translated to Javascript as the following snippet:
I defined inside my Script folder two main folders, and I structured my js files as follow:
shared //Contains the shared js files
-file1.js
-file2.js
pages //One file per page
page1.js
page2.js
...
Ticket.js // page 4 :)
Each js file is a separate module defined with the following pattern:
Note: Inside init function is registered every callback function to the window events and occasionally a $(document).ready(function(){}) block.
;(function () {
"use strict";
function Ticket(settings) {
this.currentPageUrls = settings.currentPageUrls;
this.currentPageMessages = settings.currentPageMessages;
this.currentPageEnums = settings.currentPageEnums;
this.currentPageParameters = settings.currentPageParameters;
this.gridManager = new window.gridManager(); //usage of shared modules
this.init();
}
Ticket.prototype.init = function () {
$("form").on("submit", function () {
$(".window-content-sandbox").addClass("k-loading");
});
...
}
Ticket.prototype.onRequestStart = function (e) {
...
}
//private functions definition
function private(a, b, c){
}
window.Ticket = Ticket;
}());
Once I need my Javascript functions defined in a module I include the associated Javascript file in the page.
An istance of my object is stored inside a variable and, on top of that, a function is bound to the widget event (see: onRequestStart).
HTML/JAVASCRIPT
#(Html.Kendo().DropDownList()
.Name("Users")
.DataValueField("Id")
.DataTextField("Username")
.DataSource(d => d.Read(r => r.Action("UsersAsJson", "User"))
.Events(e => e.RequestStart("onRequestStart"))))
var settings = {};
var ticket = new window.Ticket(settings);
function onRequestStart(e){
ticket.onRequestStart(e);
}
I feel like my design pattern might be unfriendly to other front-end delevoper as I am, mostly because I choose not to implement the Javascript modules within Jquery plugin.
First, Am I doing everything the wrong way?
Second, is my design pattern suitable for a Javascript test-framework?
Third, which are the must-have scenarios for Jquery plugins?
Update
Added the Javascript output by the above Razor syntax.
Folder structure
In terms of functionality (shared) and modules (modular approach), the development or application code should represent what you can encounter in HTML. A simple ctrl+f over your solution should yield all possible changes. From that experience over the years I personally prefer dividing it in:
app (application code)
classes (reusable)
modules (singleton)
lib (package manager/grunt/gulp/...)
jquery (proper library names/unminified dist file or root file)
kendo
File names
Representing what something does and to be able to reuse it in a blink of an eye is what will cut your development time. Choosing proper names has value as I'm sure you are aware. My file names always starts with the namespace usually in short followed by a reusable "search" term:
app/prototypes
ns.calendar.js (multiple configs)
ns.maps.js (combinations or single uses)
ns.places.js (forms or map add-ons)
ns.validation.js (multiple forms and general handling)
app/singletons
ns.cookiebox.js (single config)
ns.socialmedia.js (single config)
ns.dom.js (provides a place for dom corrections, global resize events, small widgets, ...)
To add, what you called shared, is functionality that's meant to be global. A great example would be to use underscore library. Or create a collection of functions (device detection, throttle, helpers in general) on your own to reuse throughout projects => ns.fn.js
Since you add them only once throughout your namespace, it's also built as singleton and can be added to the modules folder or directly in the app root.
As last addition a loader file to kickstart your point of control => ns.load.js in the app root. This file holds the single DOM ready event to bind protoypes and modules.
So you might want to rethink your idea of dividing into pages. Trust me, I've been there. At some point you'll notice how functionality grows too large in order to configure all pages separately and therefor repeatedly.
File structure
To be honest I like Tip 1 of #TxRegex answer the most, with a small addition to bind the namespace and pass it from file to file as it get's loaded.
Core principle: IIFE bound to window object
window.NameSpace = (function($, ns){
'strict'
function private(){}
var x;
ns.SearchTerm = {};
return ns;
}(window.jQuery, window.NameSpace || {}));
For more example code I'd like to point out my github account.
Bundling
Try to achieve a single bundled and minified file from lib to app, loaded in the head on async for production releases. Use separated and unminified script files on defer for development and debug purposes. You must avoid inline script with global dependencies throughout the whole project if you do this.
path to js/lib/**/*.js (usually separated to keep sequential order)
path to js/app/ns.load.js
path to js/app/ns.fn.js
path to js/app/**/*.js (auto update the bundle)
Output => ns.bundle.js
=> ns.bundle.min.js
This way you'll avoid render blocking issues in JavaScript and speed up the loading process which in turn boosts SEO. Also enables you to combine functionality for mobile layouts and desktop layouts on the fly without memory issues or jerky behavior. Minifies really well and generates little overhead in calling instances from the loader file. As a single bundle will be cached throughout your pages it all depends on how many dependencies or libraries you can cut from the bundle. Ideally for medium and large projects where code can be shared and plugged in to different projects.
More info on this in another post.
Conclusion
First, Am I doing everything the wrong way?
Not at all, your modular approach seems ok...
It's missing a global namespace, which is hard to avoid without at least one. You create one for each module but it seems better to group them all under one namespace so you can differentiate library code from application code in the window object.
Kendo seems to create inline scripts? Can't you counter the placement server side?
Second, is my design pattern suitable for a Javascript test-framework?
Except for the Kendo instances, you can add a layer for testing purposes. Remember if jQuery is your dependency inline, you'll have to render block it's loading. Otherwise => jQuery is undefined
Exclude Kendo dependencies from the bundle if you can't control the inline script. Move to a </body> bundled solution.
Third, which are the must-have scenarios for Jquery plugins?
modular approach
configurable approach for multiple instances (tip: moving all strings from your logic, see how Kendo uses object literals)
package manager to separate the "junk" from the "gold"
grunt/gulp/... setup to separate scss and css from js
try to achieve a data-attribute binding, so once all is written, you configure new instances through HTML.
Write once, adapt easily where necessary and configure plenty!
The organization and pattern seems fine, but I have some tips:
Tip 1:
Instead of setting specific global variables within your module, perhaps you could return the object instead. So instead of doing this:
;(function () {
"use strict";
function Ticket(settings) {
console.log("ticket created", settings);
}
...
window.Ticket = Ticket;
}());
You would do this:
;window.Ticket = (function () {
"use strict";
function Ticket(settings) {
console.log("ticket created", settings);
}
...
return Ticket;
}());
The reason for this is to be able to take your module code and give it a different global variable name if needed. If there is a name conflict, you can rename it to MyTicket or whatever without actually changing the module's internal code.
Tip 2:
Forget Tip 1, global variables stink. Instead of creating a seperate global variable for each object type, why not create an object manager and use a single global variable to manage all your objects:
window.myCompany = (function () {
function ObjectManager(modules) {
this.modules = modules || {};
}
ObjectManager.prototype.getInstance = function(type, settings) {
if (!type || !this.modules.hasOwnProperty(type)) {
throw "Unrecognized object type:";
}
return new this.modules[type](settings);
};
ObjectManager.prototype.addObjectType = function(type, object) {
if (!type) {
throw "Type is required";
}
if(!object) {
throw "Object is required";
}
this.modules[type] = object;
};
return new ObjectManager();
}());
Now each of your modules can be managed with this single global object that has your company name attached to it.
;(function () {
"use strict";
function Ticket(settings) {
console.log("ticket created", settings);
}
...
window.myCompany.addObjectType("Ticket", Ticket);
}());
Now you can easily get an instance for every single object type like this:
var settings = {test: true};
var ticket = window.myCompany.getInstance("Ticket", settings);
And you only have one global variable to worry about.
You can try separating your files in different components asuming each component has a folder.
for example: page 1 is about rectangles so you make a folder call rectangle inside that folder you create 3 files rectangle.component.html, rectangle.component.css, rectangle.component.js (optional rectangle.spec.js for testing).
app
└───rectangle
rectangle.component.css
rectangle.component.html
rectangle.component.js
so if anything bad happends to a rectangle you know where is the problem
a good way to isolate variables and execute in the right place is to use a router basically what this does it check at the url and executes the portion of code you asign to that page
hope it helps let me know if you need more help.

How to organize the architecture of javascript form generator using a templates and BEM methodology?

How to organize the architecture javascript-generator forms using a template and BEM methodology?
Good day!
The essence of the problem is as follows:
It is necessary to organize the generator forms based on json file with the description of control, like:
"Order": ["input1", "input2", "cb3"],
"Input1": {
"Type": "input",
"Title": "The first INPUT"
"Path": "root.input",
"Visible": true,
"Editable": true
}
"Input2": {...}
Types available for processing controls should be easily extensible. The data in the control must be extracted from the data source (they are available in the lines, paths in the property path, described in the control). The data source must be placed in a separate module, and shall provide public methods to retrieve data from it in the ways.
Working with the DOM should occur through the jQuery library, or (preferably) i-bem. It is necessary to describe the controls and components of the page in the ideology of BEM.
As the template syntax to use syntax mustache.
Using jquery + mustache. Deliberate over whether to use the organization to require js mvc application structure.
Can you please tell how to better organize the application architecture using a template mustache? (Because before they were not encountered, just beginning to learn)
How can I apply the BEM-approach without using BEM technology stack?
PS. Sorry for my English.
i-bem.js implementation for a block which should generate controls inside of it can look like this:
modules.define('form', ['i-bem__dom', 'mu', 'tmpl'], function(provide, BEMDOM, mu, tmpl) {
provide(BEMDOM.decl(this.name, {
onSetMod: {
js: {
inited: function() {
this.generate(this.params);
}
}
},
generate: function(opts) {
var html = opts.Order.map(function(control) {
return mu.render(tmpl, buildopts[control]); // assuming you have client-size mustache renderer in mu module and compiled templates in tmpl
}).join('');
BEMDOM.append(this.domElem, html);
}
}));
});
So it HTML you'll get
<form class="form i-bem" data-bem="{'form':{ HERE GOES JSON DESCRIPTION OF COMPONENTS YOU SUGGESTED }}"></form>. When form will be inited, it'll iterate over Order array and append the result of templates rendering inside of itself.

Windows Phone App in JavaScript with AngularJS

I am developing a Windows Phone Application in JavaScript. I am using the AngularJS library. The problem is that I cannot add a dynamic content because of security reasons.
The error I get: HTML1701: Unable to add dynamic content '<div id="view_login" class="view"> <div id="view_login_container"> <img class="logo" src="http://oi60.tinypic.com/okwifa.jpg"> <input type="text" placeholder="Username" ng-model="loginUsername"> <input type="password" placeholder="******" ng-model="loginPassword"> <button ng-click="doLogin()">Login</button> <button ng-click="changeView('/signup')" class="link">... or sign up now</button> </div> </div>'. A script attempted to inject dynamic content, or elements previously modified dynamically, that might be unsafe. For example, using the innerHTML property to add script or malformed HTML will generate this exception. Use the toStaticHTML method to filter dynamic content, or explicitly create elements and attributes with a method such as createElement. For more information, see http://go.microsoft.com/fwlink/?LinkID=247104.
I changed one line in AngularJS library which should fix the problem:
append:function(a,c){
**MSApp.execUnsafeLocalFunction(function () {**
r(new N(c),function(c){
1!==a.nodeType&&11!==a.nodeType||a.appendChild(c)
})
});
}
Unfortunately it did not work.
I spent several hours trying to find a solution, but I did not manage it. I would appreciate any suggestions how to make working the Windows Phone App written in JavaScript with AngularJS.
Microsoft Open Technologies recently released a shim which will prevent this exact problem for Windows Store apps using AngularJS, as well as many other popular JavaScript libraries.
Simply download the JavaScript Dynamic Content shim off of GitHub, then reference the file towards the beginning of your app before any other scripts are run. You should no longer see a dynamic content error.
Let me know if this solves your problem!
I encountered this issue when using Angular in a Windows Store App. The solution I came up with was to monkey patch the DOM manipulation functions that were unsafe, rather than having to hack up Angular or jQuery because I still wanted to be able to update using bower.
var patch = {
methods: [
'appendNode',
'cloneNode',
'insertBefore',
'removeChild',
'replaceChild'
],
properties: [
'innerHTML',
'outerHTML'
]
};
patch.methods.forEach(function (name) {
proxyUnsafeMethod(HTMLElement.prototype, name);
});
patch.properties.forEach(function (name) {
proxyUnsafeProperty(HTMLElement.prototype, name);
});
function proxyUnsafeMethod(object, name) {
var _unsafe = object[name];
object[name] = function () {
var context = this;
var args = arguments;
return MSApp.execUnsafeLocalFunction(function () {
return _unsafe.apply(context, args);
});
};
}
function proxyUnsafeProperty(object, prop) {
var descriptor = Object.getOwnPropertyDescriptor(object, prop);
proxyUnsafeMethod(descriptor, 'set');
Object.defineProperty(object, prop, descriptor);
}
Angular dynamically puts HTML comment tags <!-- --> for ng-repeat and other directives. Unfortunately, Microsoft considers these to be unsafe when put in from javascript using element.innerHTML, and thus is not allowed.
The workaround is to modify the actual angular.js file and wrap all element.innerHTML calls in MSApp.execUnsafeLocalFunction();
In the version of Angular that I'm using, this is line 2539 and line 2162
Line 2539:
MSApp.execUnsafeLocalFunction(function() { element.innerHTML = value; });
Line 2162:
MSApp.execUnsafeLocalFunction(function() { div.innerHTML = '<div> </div>' + element });
The best method would be to search the angular.js file for all instances of innerHTML and wrap it.
In a lot of cases where you run into issues with dynamic content Winstore-jsContrib might help. Simply add the .js file at the beginning of your app and you're good to go.

express3-handlebars and 18next-node - internationalisation based on page?

my first question here - please go easy. I'm using express, express3-handlebars and i18next-node with node.js
The plan is to work with a different translation namespace depending on which view (i.e. which handlebars file) is currently being served. So if we're looking at the page called ie(.hbs), i18next will look in the namespace called ie(.json) for the relevant language. This makes organisation and coordination of translations easier.
This is how I'm currently doing it: first I send the current page into the handlebars template for rendering (even this seems unnecessary - handlebars doesn't automatically expose which file it's rendering?):
res.render( url_base_path, { layout: ("sub"), title: title, currentpage: url_base_path } );
and then I access the variable "greeting" to be translated in the namespace of the current page like so {{t "greeting" page=currentpage }} - the annoying thing is that there are 10's of these variables on each page. Don't Repeat Yourself, anybody?
't' is defined in the express3-handlebars create() function, like so, helpers: { t: t }
and the translate function looks like this
var t = function (i18next_key, options) {
var page, result;
page = options.hash.page;
result = i18next.t(page + ":" + i18next_key);
return new hbs.handlebars.SafeString(result);
};
for the sake of full disclosure, this is what my (english) namespace file for the current page looks like
{
"greeting": "Hello, it appears you're using Internet Explorer, an outdated web browser."
}
this works, but it seems like there should be a much simpler solution.
what i really want is to be able to just type {{t "greeting"}} into the handlebars template to achieve the same result. is this possible without overriding core handlebars functionality?
here is the i18next docs page
http://i18next.com/pages/doc_features.html
I've answered my own question - it turned out easier than I expected.
You can access the handlebars instance in my Handlebars translate helper (duh?), so in the helper: renderer = this (for clarity), then you can just access renderer.currentpage to get the name of the required namespace. Note, you still have to send currentpage in the render function (on res.render()), but I'm ok with that side of it.
I've done it like this (it's probably pretty slow like this at the moment, but it works exactly how I want it to):
// Set namespace for translation
options.ns = options.ns || bestNamespaceFor( i18n_key );
result = i18n.t(i18n_key, options);
return new hbs.handlebars.SafeString(result);
function bestNamespaceFor( i18n_key ){
if ( i18n.exists(i18n_key, { ns: renderer.currentpage }) ) return renderer.currentpage;
if ( i18n.exists(i18n_key, { ns: renderer.layout }) ) return renderer.layout;
if ( i18n.exists(i18n_key, { ns: "common" }) ) return "common";
Works perfectly with {{t "my translation key" }} and gets the right namespace no matter where I use it.

Categories

Resources