Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a support for ngCloak \ prevent keys appearing on first page load #237

Closed
BeOleg opened this issue Nov 20, 2013 · 26 comments
Closed

Add a support for ngCloak \ prevent keys appearing on first page load #237

BeOleg opened this issue Nov 20, 2013 · 26 comments

Comments

@BeOleg
Copy link

@BeOleg BeOleg commented Nov 20, 2013

On the first load of the page the phrase keys appear for several instances instead of the translated values.
tried using ng-bind-template, but no luck, the problem is because I am only getting the user's language by an ajax request.
And setting the wrong language by default is as much bad as showing the phrase keys.

Any thoughts?

@frapontillo
Copy link

@frapontillo frapontillo commented Nov 21, 2013

This happens because the translate method returned by the provider always returns back the translationId. I don't know how this can currently be solved, though. It'd be nice to have some sort of temporary "fallback" for undefined or not yet translated ids.

Ideas?

@PascalPrecht
Copy link
Member

@PascalPrecht PascalPrecht commented Nov 21, 2013

@BeOleg @frapontillo Its just a logical behaviour. $translate service tries to translate a given translation id. If this isn't present, it tries the same with a fallback language. If the translation ids also doesn't exist in the fallback language translation table, then the translation id itself gets returned.

When using an asynchronous loader and not providing a default language statically (by adding it via $translate.translations()), then of course you'll have a FOUC - Flash of untranslated content.

To get around this, you have to provide at least one language statically, preferably its the default language (the one you configure with $translate.preferredLanguage() or you have to listen for the very first $translateChangeSuccess event and apply a class or so.

Here are some resources:

FOUC: http://pascalprecht.github.io/angular-translate/docs/en/#/guide/10_asynchronous-loading#foucflashofuntranslatedcontent

Events: http://pascalprecht.github.io/angular-translate/docs/en/#/guide/16_events

hope this helps.

@frapontillo
Copy link

@frapontillo frapontillo commented Nov 21, 2013

So can I provide a static subset of basic defaults of a language (e.g. 'en-US'), that will then be overridden by, for example, $translateProvider.useStaticFilesLoader?
This way I'd be able to use a static text until the files loader does its stuff.
Thank you.

@PascalPrecht
Copy link
Member

@PascalPrecht PascalPrecht commented Nov 21, 2013

@frapontillo unfortunately you cannot set a subset of translations when using staticFilesLoader. If you want to add translations statically, you have to add a whole language, so a complete translation table. Because, when using the asynchronous loader, $translate service only loads the language asynchronously that doesn't exist yet. Which means, when adding a language statically statically, this language actually already exists, so it doesn't try to load it.

What you want is the partialLoader. You can actually do exactly that with the partialLoader. Unfortunately there's a little bug, which is fixed in canary but not landed in master yet. Expect a release in the next few days!

@PascalPrecht
Copy link
Member

@PascalPrecht PascalPrecht commented Nov 25, 2013

@frapontillo Landed yesterday in master by the way.

@frapontillo
Copy link

@frapontillo frapontillo commented Nov 25, 2013

Great, thanks! 👍

@devorbitus
Copy link

@devorbitus devorbitus commented Dec 6, 2013

Just out of curiosity, why not an option in the provider allowing for the directive to hide content until the asynchronous call to get translations returns?

@PascalPrecht
Copy link
Member

@PascalPrecht PascalPrecht commented Dec 6, 2013

@devorbitus Could you please be a bit more concrete :) ? Pseudo example? Just to make sure I'll answer with the right arguments.

@devorbitus
Copy link

@devorbitus devorbitus commented Dec 7, 2013

In my case I just monkey patched the finished angular-translate.js file to add the following if statement just inside the link function of the translate directive...

if (!(attr.translateHideUntil == undefined)){
    element.hide();
    scope.$on('$translateLoadingSuccess',function(){
        element.show();
    });
}

Then I placed the translate-hide-until attribute on the element I wanted hidden and it remained hidden until translations arrived.

The correct way to do this at a project level would be to add an option to the provider but I only had a couple items in my header that were FOUC.

@devorbitus
Copy link

@devorbitus devorbitus commented Dec 7, 2013

To me, this just makes more sense than having to include a default language. Especially on a finished product that might be white labeled for different languages for different customers. You wouldn't want your German only customer to be forced to see a flash of English.

@PascalPrecht
Copy link
Member

@PascalPrecht PascalPrecht commented Dec 16, 2013

@devorbitus I agree that we need another/a better solution for that, but I'm not sure if it's a good thing to show/hide on each element that has translate directive.

@devorbitus
Copy link

@devorbitus devorbitus commented Dec 16, 2013

Yeah, I am in now way advocating for this to be the default behaviour just an option.

@alex6o
Copy link

@alex6o alex6o commented Jan 8, 2014

+1

1 similar comment
@lpsBetty
Copy link

@lpsBetty lpsBetty commented Jan 13, 2014

+1

@lpsBetty
Copy link

@lpsBetty lpsBetty commented Jan 13, 2014

I'm using the Url Loader, so when the server response is slow it shows the i18n keys.. not very nice ;)

@PascalPrecht
Copy link
Member

@PascalPrecht PascalPrecht commented Jan 13, 2014

@IpsBetty i'm on it.

@lpsBetty
Copy link

@lpsBetty lpsBetty commented Jan 13, 2014

@PascalPrecht sehr cool!

@BeOleg
Copy link
Author

@BeOleg BeOleg commented Jan 13, 2014

Great @PascalPrecht !
Thanks!, keep us posted!

@pedrosanta
Copy link

@pedrosanta pedrosanta commented Jan 14, 2014

+1

@avmolchanov
Copy link

@avmolchanov avmolchanov commented Jan 23, 2014

Hi @PascalPrecht! We are looking to use the feature in our product but this FOUC thing makes us put internationalization on hold. Is there a workaround that would help to pre-load selected (e.g. German) translation table synchronously? Thanks. BTW, the framework is great!

@PascalPrecht
Copy link
Member

@PascalPrecht PascalPrecht commented Jan 23, 2014

@avmolchanov Well I think the only thing you can do is to ship your app with at least one language and make that language the preferred language.

@PascalPrecht
Copy link
Member

@PascalPrecht PascalPrecht commented Jan 23, 2014

Actually i'm working on a 2.0 release and want to address all issues there, but it seems like it'll take to much time. So i'll probably cherry pick some already implemented features and do some minor releases.

@avmolchanov
Copy link

@avmolchanov avmolchanov commented Jan 23, 2014

Great, thanks!

@frapontillo
Copy link

@frapontillo frapontillo commented Jan 23, 2014

@avmolchanov you can still rely on the resolve mechanism (based on promises) to load all of the data (including the default language) before initializing the controller, and thus the view. The problem persists for the page title and other pre-angular elements, but that's a completely different story.

@knalli
Copy link
Member

@knalli knalli commented Jan 24, 2014

We are looking to use the feature in our product but this FOUC thing makes us put internationalization on hold.

Actually, you can deal with this on your own. You introduce a scope expression defining whether translation (or even other i18n stuff) is already loaded or not. Unless it is loaded, you will show something like a splashscreen, a styled "blank" screen or whatever. The only have to is more or less the page title, which can be handled either with an own dedicated "setPageTitle" using the $translate-service functionality which recognize untranslated values or a pseudo language which with only one key (i.e. language 'xx').

So, in a nutshell:

$rootScope.i18nLoaded = false;
$rootScope.$on('translateChangeSuccess', function () {
  $rootScope.i18nLoaded = true;
});
<body>
  <main ng-show="i18nLoaded">Loading...</main>
  <main ng-hide="i18nLoaded">>ourapp</main>
</body>

Using a pseudo language would be:

  1. Set the used language to XX
  2. Set the language directly, only the required keys.
  3. Invoke immediately the preferred language which would invoke itself change events later.

Actually, you should have already that kind of mechanisms or how you deal with user sessions and session located locales?

@PascalPrecht
Copy link
Member

@PascalPrecht PascalPrecht commented Feb 9, 2014

Implemented in canary right here: c125c56 will be released probably next week

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
9 participants
You can’t perform that action at this time.