Meteor accounts.ui localization - localization

I'm learning to use meteor.
Is it possible to easily localize accounts.ui components?

This is a slightly hacky solution, you could remove the accounts-ui package you have and add it in manually. Find the accounts-ui branch on meteor's github repo and find all the contents in the accounts-ui package such as: login_buttons_dialogs.html, login_buttons.html, etc.
You could then edit and copy these files into your meteor project directly with the custom text in the language you would like.
Meteor hasn't implemented internationalization but its on the roadmap. What you could do is use meteorite and install a localization package such as simple-i18n in conjunction with the manually edited accounts-ui files to give your users a multi-lingual experience or simply offer accounts-ui in a different language.

Here is a trick I have used. Simple, but works:
Template.header.rendered = function() {
$('#login-sign-in-link').text('Přihlásit se ▾');
$('.login-close-text').text('Zavřít nabídku');
$('.sign-in-text-google').text('Přihlásit se přes Google');
$('.sign-in-text-facebook').text('Přihlásit se přes FB');
//etc...
};

For portuguese (PT-BR)
Template.layout.rendered = function() {
$('#login-sign-in-link').text('Login ▾');
$('.login-close-text').text('Fechar');
$('#login-username-or-email-label').text('Nome de usuário ou e-mail');
$('#login-password-label').text('Senha');
$('#signup-link').text('Criar uma conta');
$('#forgot-password-link').text('Esqueceu a senha?');
$('#login-buttons-forgot-password').text('Recuperar');
$('#back-to-login-link').text('Login');
$('#login-username-label').text('Usuário para login');
$('#login-buttons-open-change-password').text('Alterar senha');
$('#login-buttons-logout').text('Logout');
if ($('#login-buttons-password').text().indexOf('Sign in') != -1) {
$('#login-buttons-password').text('Login');
} else {
$('#login-buttons-password').text('Criar conta');
}
$('.login-button').addClass('btn btn-warning');
$('.login-button').removeClass('login-button login-button-form-submit');
if ($('.message.error-message').text().indexOf('Username must be at least 3 characters long') != -1) {
$('.message.error-message').text('Usuário deve ter pelo menos 3 caracteres');
} else if ($('.message.error-message').text().indexOf('Incorrect password') != -1 || $('.message.error-message').text().indexOf('User not found') != -1) {
$('.message.error-message').text('Usuário/senha errado(s)');
}
$('#login-old-password-label').text('Senha atual');
$('#login-buttons-do-change-password').text('Alterar a senha');
$('#reset-password-new-password-label').text('Nova senha');
$('#login-buttons-reset-password-button').text('Alterar');
if ($('.message.info-message').text().indexOf('Email sent') != -1) $('.message.info-message').text('E-mail enviado');
$('#just-verified-dismiss-button').parent().html('Email verificado <div class="btn btn-warning" id="just-verified-dismiss-button">Ocultar</div>');
};
WATCH OUT BOYS!
The CLOSE in the $('.login-close-text') is the VERB... TO CLOSE
It does not mean "NEAR" as I may have read in some answers above.

For french:
/**
* Accounts-ui ugly translation
* TODO : use i18n solution
*/
Template.header.rendered = function() {
$('#login-sign-in-link').text('Connexion ▾');
$('.login-close-text').text('Fermer');
$('#login-username-or-email-label').text('Pseudo ou email');
$('#login-password-label').text('Mot de passe (mdp)');
$('#signup-link').text('Créer un compte');
$('#forgot-password-link').text('Mdp oublié');
$('#login-buttons-forgot-password').text('Récupération');
$('#back-to-login-link').text('Connexion');
$('#login-username-label').text('Pseudo');
$('#login-buttons-open-change-password').text('Changer de mdp');
$('#login-buttons-logout').text('Deconnexion');
if ($('#login-buttons-password').text().indexOf('Sign in') != -1) {
$('#login-buttons-password').text('Connexion');
} else {
$('#login-buttons-password').text('Créer le compte');
}
$('.login-button').addClass('btn btn-warning');
$('.login-button').removeClass('login-button login-button-form-submit');
if ($('.message.error-message').text().indexOf('Username must be at least 3 characters long') != -1) {
$('.message.error-message').text('Le login doit faire plus de 3 caractères');
} else if ($('.message.error-message').text().indexOf('Incorrect password') != -1 || $('.message.error-message').text().indexOf('User not found') != -1) {
$('.message.error-message').text('login ou mot de passe incorrect');
}
$('#login-old-password-label').text('Mot de passe actuel');
$('#login-buttons-do-change-password').text('Changer le mot de passe');
$('#reset-password-new-password-label').text('Nouveau mot de passe');
$('#login-buttons-reset-password-button').text('Changer');
if ($('.message.info-message').text().indexOf('Email sent') != -1) $('.message.info-message').text('Email envoyé');
$('#just-verified-dismiss-button').parent().html('Email vérifié <div class="btn btn-warning" id="just-verified-dismiss-button">Masquer</div>');
};

i18n is still on the todo list of Meteor. Meanwhile, you can cook a system of your own.
Se how they achieved internationalisation here for example: https://github.com/bolora/multi-page-config

For German, including all labels.
This is mostly adapted from Pascoual's post, however, the buttons are still formatted and some additional labels are translated...
If you find a label which still isn't translatet, please report this in a comment.
/**
* Accounts-ui ugly translation
* TODO : use i18n solution
*/
Template.login.rendered = function() {
$('#login-sign-in-link').text('Einloggen');
$('.login-close-text').text('Schliessen');
$('#login-username-or-email-label').text('Benutzername oder Email');
$('#login-password-label').text('Passwort');
$('#signup-link').text('Konto erstellen');
$('#forgot-password-link').text('Passwort vergessen');
$('#login-buttons-forgot-password').text('Wiederherstellen');
$('#back-to-login-link').text('Zurück');
$('#login-username-label').text('Benutzername');
$('#login-buttons-open-change-password').text('Passwort ändern');
$('#login-buttons-logout').text('Logout');
$('#reset-password-new-password-label').text('Neues Passwort');
$('#login-old-password-label').text('Aktuelles Passwort');
$('#login-password-label').text('Neues Passwort');
$('#login-buttons-do-change-password').text('Passwort ändern');
if ($('#login-buttons-password').text().indexOf('Sign in') != -1) {
$('#login-buttons-password').text('Einloggen');
} else {
$('#login-buttons-password').text('Konto erstellen');
}
if ($('.message.error-message').text().indexOf('Username must be at least 3 characters long') != -1) {
$('.message.error-message').text('Benutzername muss mindestens 3 Zeichen lang sein');
} else if ($('.message.error-message').text().indexOf('Incorrect password') != -1 || $('.message.error-message').text().indexOf('User not found') != -1) {
$('.message.error-message').text('Benutzername oder Passwort falsch');
}
};

The simplest way is to user accounts-tap package:
https://atmospherejs.com/softwarerero/accounts-t9n
It is based on tapi18n, you have just to add the following configuration on client side :
T9n.setLanguage('<yourLanguage>')

You can consider to use meteor-accounts-ui-bootstrap-3
It supports localization:
accountsUIBootstrap3.setLanguage('ru');

Related

How to listen keyup events outside any input on iOS with Ionic 3

My problem is quite simple, and I think I know the answer, but if I'm wrong it could be great …
I would like to use an external barcode scanner (work like a physical bluetooth keyboard) to read barcodes but outside any input.
I made a piece of code which works great on android devices but nothing happend on iOS devices …
I'll make it quick, I listen «keyup» events on «window» and when I catch the «Enter» key, I emit the barcode event …
I use RxJS and Observable fromEvent and everithing works great on Android devices.
Is the Safari WebView the problem ?
I remember I already had the same issue on website, Safari does not trigger keyboard events outside elements which don't require keyboard (input, textarea …)
/**
* Outil pour traiter la lecture d'un codebarre par un lecteur physique
* Seuls les évènements claviers hors input sont récupérés
*/
export namespace LecteurCodebarrePhysique {
// L'évènement est-il dans un input ?
const inInput = (event) => {return event.target instanceof Element && event.target.nodeName.toLowerCase() === 'input'};
// La touche relachée est-elle un caractère ?
const isTextKey = (event) => {return !inInput(event) && event.key.length === 1};
// La touche relachée est-elle la touche entrée ?
const isEnter = (event) => {return !inInput(event) && event.keyCode === 13};
/**
* Observable émettant le codebarre lu par un lecteur physique
*/
export function codebarreLu(): Observable<{text: string, format: string}> {
// Observable initiale : évèrement clavier
const keyup: Observable<KeyboardEvent> = fromEvent(window, 'keyup');
return keyup.pipe(
// On ne garde que les touches représentant un caractère
filter(ev => isTextKey(ev)),
// On ne garde que la valeur du caractère
map(ev => ev.key),
// On «bufferise» en attendant la touche entrée
buffer(keyup.pipe(filter(ev => {
const enter = isEnter(ev);
if (enter) {
ev.preventDefault();
ev.stopPropagation();
}
return enter;
}))),
// Quand la touche entrée est relachée, on concatène les caractères
// Et on essaye de déterminer si c'es un EAN13 (13 caractères numériques)
map(chars => {
const codebarre = chars.reduce((code, char) => code + char, '');
const isEan13 = /\d{13}/.test(codebarre);
return {text: codebarre, format: isEan13 ? 'EAN_13' : 'INCONNU'};
})
);
}
}
On Android devices, if I subscribe to the observable and read a barcode outside any inputs, the code inside the subscription is called.
On iOS devices, nothing happend …
Eureka!
If other guys have the same issue/need of me, I post here the answer! Yes I'm too kind ^^
I've changed the target of the event from «window» to «document» and … wait for it … It works.

Empty FullText property with Tweetmode.Extended [update May 30th]

I'm programming a .Net Core (2.1 preview, C# 7.3) Streaming Console App with L2T (5.0.0 beta 2) but even with the strm.TweetMode == TweetMode.Extended the query gives "compat" tweets back, the FullText property is empty.
You can reproduce this with the L2T query below.
I searched online, I've found something similar (with 'search' instead of 'Streaming') but no answers, except to add && strm.TweetMode == TweetMode.Extended, which I did.
Any ideas?
try
{
await
(from strm in twitterCtx.Streaming
.WithCancellation(cancelTokenSrc.Token)
where
strm.Type == StreamingType.Filter
&& strm.Track == "twitter"
&& strm.Language == "nl"
&& strm.TweetMode == TweetMode.Extended
select strm)
.StartAsync(async strm =>
{
await HandleStreamResponse(strm);
if (count++ >= 20)
cancelTokenSrc.Cancel();
});
}
[Update May 30th]
Found something. It's in the subroutine "HandleStreamResponse" (code below). The Status.TweetMode and Status.ExtendedTweet.TweetMode both return "Compat" for all tweets, but the full text of a tweet is in status.ExtendedTweet.FullText
But even with this check, retweets are truncated to 140 chars max. I do not need retweets for my progam so I filter them out.
I do not know, yet, how to filter retweets from a stream directly (is it possible?), so I check the retweetstatus of the Status from the stream result. It's in the code below.
FYI: In the examples of Linq To Twitter for this subroutine Joe Mayo uses the following line of code, but that doesn't work: Console.WriteLine("{0}: {1} {2}", status.StatusID, status.User.ScreenNameResponse, status.Text ?? status.FullText);
Even with && strm.TweetMode == TweetMode.Extended in the L2T query, the status.FullText is empty.
There is more code than neccesary in the example below, but I used it for clarity.
static async Task<int> HandleStreamResponse(StreamContent strm)
{
switch (strm.EntityType)
{
case StreamEntityType.Status:
var status = strm.Entity as Status;
if (status.RetweetedStatus.StatusID == 0)
{
if (status.ExtendedTweet.FullText != null)
{
Console.WriteLine("Longer than 140 - \"#{0}\": {1} (TweetMode:{2})",
status.User.ScreenNameResponse, status.ExtendedTweet.FullText, status.TweetMode);
}
else
{
Console.WriteLine("Shorter than 140 - \"#{0}\": {1} (TweetMode:{2})",
status.User.ScreenNameResponse, status.Text, status.TweetMode);
}
}
// Console.WriteLine("{0}: {1} {2}", status.StatusID, status.User.ScreenNameResponse, status.Text ?? status.FullText);
break;
default:
Console.WriteLine("Unknown - " + strm.Content + "\n");
break;
}
return await Task.FromResult(0);
}
}
Here are my observations:
status.ExtentendedTweet.FullText should hold the tweet in normal circumstances.
However, if the tweet is retweeted, then status.RetweetedStatus.ExtendedTweet.FullText should hold the tweet.
If you can't find the FullText in either of those circumstances, use status.Text.
I'm updating the sample with the following:
case StreamEntityType.Status:
var status = strm.Entity as Status;
string text = null;
if (status.ExtendedTweet?.FullText != null)
text = status.ExtendedTweet?.FullText;
else if (status.RetweetedStatus?.ExtendedTweet?.FullText != null)
text = status.RetweetedStatus?.ExtendedTweet?.FullText;
else
text = status.Text;
Console.WriteLine("Status - #{0}: {1}", status.User.ScreenNameResponse, text);
break;
Note: Via Twitter documentation (see Standard Streams), TweetMode doesn't apply to streams. Additionally, the docs say the ExtentedTweet should always be there with FullText. As we can see, that isn't the full picture in practice. I'll mark Streaming.TweetMode as obsolete in upcoming releases.

Saving in Elasticsearch with Spark Streaming issue

I am trying to save in Elasticsearch using Spark Streaming. The code works, but it only saves to elastic search once i stop the process (i am launching it from intelliJ IDEA).
i need to save twitts as long as they come in streaming.
Thanks!
Here is my code:
tweets.foreachRDD(tweet => {
if (tweet.isEmpty) {
println("no se han recibido tweets en este tramo de tiempo")
} else {
val tweetsRdd = tweet.map(t => {
System.out.println(t.getText)
var country = ""
if (t.getPlace() != null) {
country = t.getPlace().getCountry()
}
val hashtag = t.getText().split(" ").filter(word => word.startsWith("#"))
Tweet(t.getUser().getName(), t.getUser().getLang(), t.getText(), t.getCreatedAt(), t.getRetweetCount(), country, t.isRetweet(), t.getUser().getFollowersCount(), hashtag)
})
EsSpark.saveToEs(tweetsRdd, index_name + "/" + type_name)
}
}
)
ssc.start()
ssc.awaitTermination()

Why IsolatingStorageSettings is empty when i restart my APP ? (WP8)

I use the IsolatingStorageSetting to store a collection of objects. It works great when my app is running but when I restart it...the collection is empty...Why does it not keep my object collection in memory.?
private void llsElements_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
LongListSelector llselement = null;
listElementCollection.Clear();
if (sender != null)
llselement =(LongListSelector)sender;
if(llselement.SelectedItem!=null)
{
BdeskElement bdelement=(BdeskElement)llselement.SelectedItem;
if (bdelement.TypeElement == BdeskElement.BdeskTypeElement.File)
{
if (!IsolatedStorageSettings.ApplicationSettings.Contains(bdelement.URLElement))//IsCached? =>NON
{
if (IsolatedStorageSettings.ApplicationSettings.Count >= 100)//Si la liste des fichiers en cache est pleine
{
string KeyOldestElement = IsolatedStorageSettings.ApplicationSettings.Last().Key;
IsolatedStorageSettings.ApplicationSettings.Remove(KeyOldestElement);//on supprime le dernier élément de la liste
if (IsolatedStorageOperations.IsFileSaved(KeyOldestElement+bdelement.Extension))
IsolatedStorageOperations.DeleteFile(KeyOldestElement+bdelement.Extension);
}
IsolatedStorageSettings.ApplicationSettings.Add(bdelement.URLElement, bdelement);//on ajoute notre élément
DownloadAndReadFile(bdelement);
}
else //Si le fichier est deja présent dans la liste (donc déja en cache)
{
if (IsFileModified(bdelement, IsolatedStorageSettings.ApplicationSettings[bdelement.URLElement]))//compare la version téléchargée et la version en cache/ les versions sont identiques
{
string FileNameFormated = bdelement.URLElement.Replace("/", "_").Substring(7, bdelement.URLElement.Length - 7);
if (IsolatedStorageOperations.IsFileSaved(FileNameFormated))
{
MessageBox.Show("Le fichier est lu dans le cache");
byte[] Encryptedbytefile = IsolatedStorageOperations.GetFile((FileNameFormated));
byte [] UnCryptedByteFile=EncryptedString.DecryptDataToData(Encryptedbytefile);
IsolatedStorageOperations.SaveToFile(UnCryptedByteFile, "FileToRead" + bdelement.Extension);
IsolatedStorageOperations.ReadFile("FileToRead"+bdelement.Extension);
}
}
else//les versions sont différentes
{
IsolatedStorageSettings.ApplicationSettings.Remove(bdelement.URLElement);//supprime l'ancienne version
IsolatedStorageSettings.ApplicationSettings.Add(bdelement.URLElement, bdelement);//ajoute la nouvelle
DownloadAndReadFile(bdelement);
}
}
}
else if (bdelement.TypeElement == BdeskElement.BdeskTypeElement.Folder)
{
//l'élément cliqué devient l'élément courant
App.CurrentFolder = bdelement;
//On raffiche la page
NavigationService.Navigate(new Uri(String.Format("/Views/BDocs/FolderView.xaml?id={0}", Guid.NewGuid().ToString()), UriKind.Relative));
}
}
IsolatedStorageSettings.ApplicationSettings.Save(); //EDITED
}
EDIT
ISSUE I HAVE ON THE SAVE METHOD
Informations supplémentaires : Type 'System.Windows.Media.ImageSource' cannot be serialized. Consider marking it with the DataContractAttribute attribute, and marking all of its members you want serialized with the DataMemberAttribute attribute. Alternatively, you can ensure that the type is public and has a parameterless constructor - all public members of the type will then be serialized, and no attributes will be required.
Probably it's because you aren't saving it - try to use IsolatedStorageSettings.ApplicationSettings.Save() when you finsh with it.
Of course it won't work when you restart the Emulator - after restarting it is a fresh instance.
EDIT - after OP's edit
You cannot serialize ImageSource - similar question is here. Instead consider serializing ImagePath.

`"` replaced with `"` when loading page

I've stumbled on a little problem when i'm viewing my page where " gets replaced with ". My page looks like this:
$(document).ready(function() {
$("input[name$='case']").click(function() {
var test = $(this).val();
if(test == "daglig"){
$("div.desc").hide();
$("#daglig_div").show();
}else if(test == "veckovis"){
$("div.desc").hide();
$("#veckovis_div").show();
}else if(test == "manadsvis"){
$("div.desc").hide();
$("#manadsvis_div").show();
}
});
});
When i'm deploying the page the result is this:
$(document).ready(function() {
$("input[name$='case']").click(function() {
var test = $(this).val();
if(test == "daglig"){
$("div.desc").hide();
$("#daglig_div").show();
}else if(test == "veckovis"){
$("div.desc").hide();
$("#veckovis_div").show();
}else if(test == "manadsvis"){
$("div.desc").hide();
$("#manadsvis_div").show();
}
});
});​
And it's only this part of the page which gets this strange convertion. I've tried with different encodings, charsets, copying other quotes on the page which doesn't get replaced with ", replaced " with " and i still get the same error. Can someone please help me on this matter?
Thanks in advance, ClydeFrog
I "rewrote" the function again myself and it's working now. Apparently the old text had different charsets then my new text i wrote. Very strange bacause i converted the old text to "UTF-8" with notepad++, but obviously it didn't work... thanks anyway to everyone who took the time :)

Resources