Git Product home page Git Product logo

Comments (30)

vrunoa avatar vrunoa commented on June 25, 2024

@chk1 I start an implementation of this adding a locale.js and the localization files inside the /locale folder.
https://github.com/Urucas/slackin/blob/master/lib/locale.js
https://github.com/Urucas/slackin/blob/master/lib/locale/en.js
https://github.com/Urucas/slackin/blob/master/lib/locale/es.js

There's a first implementation on splash.js

// import 
import locale from './locale'

export default function splash({ name, logo, active, total, channel, iframe, lang }){

  let locale = locale('es');
  // ...
  dom('p', locale('join', [name, channel])),
  // ...
}

What do you think guys ? @chk1 @rauchg @brianloveswords

from slackin.

rauchg avatar rauchg commented on June 25, 2024

Great work

  • I wouldn't rely on dynamic require, since it's not very ES6-y.
  • Instead, I would import the known languages manually from locale.
  • In the main constructor (slackin), I would make it possible to pass more locales, so that they're extensible.
  • Why export translate instead of export default?

from slackin.

rauchg avatar rauchg commented on June 25, 2024

You can also take advantage of template strings and function parameters that are statically analyzable:

// es.js
export function join({ room, channel }){
  return `Unirse a <b>${room}</b> ${channel} on Slack`;
}

from slackin.

rauchg avatar rauchg commented on June 25, 2024

For tags you're gonna have to actually return elements:

return ['Unirse a ', dom('b', room), ' on Slack'];

from slackin.

vrunoa avatar vrunoa commented on June 25, 2024

Thanks for your reply @rauchg , tonight i'll make some fixes over the code and give you feedback. @chk1 let me know if you want to contribute i'll add you to our repo as a contributor.

Yeah, my mistake on the require 😞

from slackin.

chk1 avatar chk1 commented on June 25, 2024

@vrunoa Thanks for the invitiations, I will gladly accept the invitation and contribute (probably not before next week though)

from slackin.

vrunoa avatar vrunoa commented on June 25, 2024

No problem @chk1 , I already added you to the repo team.

from slackin.

vrunoa avatar vrunoa commented on June 25, 2024

Hey guys I added a few changes to implement the translations

I change bin/slackin to receive more than one language param and pass them to (slackin) constructor.

https://github.com/Urucas/slackin/blob/master/bin/slackin#L22-L24

program.lang = !program.args[2] ? 
  ['en'] : 
  program.args.slice(2, program.args.length);

and creating as many instances as language params passed in the (slackin) constructor.
https://github.com/Urucas/slackin/blob/master/lib/index.js#L27

export default function slackin({
  token,
  interval = 1000, // jshint ignore:line
  org,
  channel,
  silent = false, // jshint ignore:line
  lang = ['en'] // jshin ignore:line
})

https://github.com/Urucas/slackin/blob/master/lib/index.js#L36-L43

// set default languaje
if (!lang) lang = ['en'];
// create localization objects
let locales = Array.from(
  new Array(lang.length), 
  (x,i) => (function(i) {
    return locale[lang[i]] ? locale[lang[i]]() : locale['en']();
  })(i)
);

add the locales as param on the (splash) constructor;
https://github.com/Urucas/slackin/blob/master/lib/index.js#L67

let dom = splash({ name, logo, channel, active, total, locales });

and inside the (splash) instance I call the current translation tag method
https://github.com/Urucas/slackin/blob/master/lib/splash.js#L13

// ...
dom('p', locale.join(name)),
dom('p.status', locale.state(active, total)),
dom('form',
  dom('input type=text [email protected] '
  + (!iframe ? 'autofocus' : '')),
  locale.getinvite() 
),
!iframe && dom('footer',
  locale.powered(),
  dom('a href=http://rauchg.com/slackin target=_blank', 'slackin')
),
// ...

described in the locale.js
https://github.com/Urucas/slackin/blob/master/lib/locale.js

export function en() {
  return {
    join: function(room) {
      return ['Join ', dom('b', room), ' on Slack'];
    },
    state: function(active, total) {
      return active ? [
        dom('b.active', active), ' users online now of ',
        dom('b.total', total), ' registered.'
      ] : [
        dom('b.total', total), ' users are registered so far.'
      ]
    },
    getinvite: function() {
      return [dom('button.loading', 'Get my Invite')];
    },
    powered: function() {
      return ['powered by '];  
    }
  }
}

export function es() {
  return {
    join: function(room) {
      return ['Unirse a ', dom('b', room), ' en Slack'];
    },
    state: function(active, total) {
      return active ? [
        dom('b.active', active), ' usuarios online de ',
        dom('b.total', total), ' registrados.'
      ] : [
        dom('b.total', total), ' usuarios registrados hasta el momento.'
      ]
    },
    getinvite: function() {
      return [dom('button.loading', 'Obtener mi invitación')];
    },
    powered: function() {
      return ['powered by '];  
    }
  }
}

What this what you guys have in mind to create the translations ? @chk1 @rauchg @brianloveswords

One question I didn't finish to understand, now that we can pass more than one language, how will the user select one? The idea is to add a select element to the ui?

from slackin.

rauchg avatar rauchg commented on June 25, 2024

As far as the constructor, I was thinking directly passing the language objects:

let english = {
  woot: () => {}
};
slackin({ langs: { en: english } })

from slackin.

vrunoa avatar vrunoa commented on June 25, 2024

So, the idea would be to move them into bin/slackin ?

Here https://github.com/Urucas/slackin/blob/master/bin/slackin#L22-L24 ?

I'm kinda lost.

from slackin.

rauchg avatar rauchg commented on June 25, 2024

Since we can't possibly support every language, we need to have an option for the user to supply the language object.

from slackin.

chk1 avatar chk1 commented on June 25, 2024

Thanks, this is great. I will contribute German language now.

@vrunoa

One question I didn't finish to understand, now that we can pass more than one language, how will the user select one? The idea is to add a select element to the ui?

I think it would be nice if Slackin chooses the language based on the user's browser setting (maybe through the HTTP Accept-Language header), if the user's language is in the list of languages set by the Slackin administrator.

from slackin.

rauchg avatar rauchg commented on June 25, 2024

User agent detection should be enough.

from slackin.

vrunoa avatar vrunoa commented on June 25, 2024

Hey guys I made some updates to (slakin);

  • Add default language to en on (slackin) constructor
langs = { en: en() }  // jshin ignore:line

https://github.com/Urucas/slackin/blob/master/lib/index.js#L28

  • Check & compare accept-language headers to select the locale from langs object
// set the locale based on Accept-Language header
let locale;
for(let key in langs){
  locale = locale || langs[key];
  if(req.headers["accept-language"].indexOf(key) == 0){
    locale = langs[key];
  }
};
let dom = splash({ name, logo, channel, active, total, locale });

https://github.com/Urucas/slackin/blob/master/lib/index.js#L61-L70

Check this link, I create a(slackin) with 3 languages(english, spanish, deutsch). @chk1 you have your browser in deutsch ? it should show (slackin) with the translation you create.

from slackin.

chk1 avatar chk1 commented on June 25, 2024

@vrunoa
Thanks for the code, it doesn't seem to work though, I always get the English version on your demo and when testing on my local machine.

It looks like this comparison fails:

req.headers["accept-language"].indexOf(key) == 0

First issue, the accept-language header (if you have set up German and English in your browser's language settings) looks similar to this: de,de-de;q=0.8,en;q=0.5,en-us;q=0.3
Your code is comparing against values like "de" or "en" as far as I can tell, so that won't work.

Second, it should probably be >= 0 (please correct me if I'm wrong), otherwise it seemed to always use English, no matter what languages I set in the start command.

I looked up some topics on how to decode this, other devs seem to suggest the npm locale module. From the examples it looks like exactly what we need here, basically "we support languages x y, your browser has y z, best match is y". I will see if I can get something to work

from slackin.

vrunoa avatar vrunoa commented on June 25, 2024

Wait @chk1, I tested and it did show me (slackin) on deutsche. I'm checkin again bin/slackin the error is there, 'cause it's just passing as param the en language instead of en, es, de.

from slackin.

chk1 avatar chk1 commented on June 25, 2024

@vrunoa Maybe I got something wrong, how do you start it with the language setting?
Just German: ./bin/slackin org xxxx-xxxx de
All languages: ./bin/slackin org xxxx-xxxx en,de,sp
Like that?

from slackin.

vrunoa avatar vrunoa commented on June 25, 2024

Yeah, that way is correct. I made a fix, last night I forgot to add langs imported on bin/slackin to the (slackin) params.

Can you check it now, https://slackin.localtunnel.me/ ?

from slackin.

chk1 avatar chk1 commented on June 25, 2024

Your version works now, I see German text 👍

from slackin.

vrunoa avatar vrunoa commented on June 25, 2024

I add a test to check everytime any user add a new translation file, this has the same & required methods as the english prototype

https://github.com/Urucas/slackin/blob/master/test/translations.js

I'll wait for @rauchg @brianloveswords reply and make a PR.

from slackin.

rauchg avatar rauchg commented on June 25, 2024

Looking really solid. Why did we decide against export join vs the function? Mind you, I actually think export default should not exist, and every module should be a function, but I'm curious.

from slackin.

rauchg avatar rauchg commented on June 25, 2024

oh btw, you don't have to return an array if it's single element. Everything gets flattened automatically.

from slackin.

vrunoa avatar vrunoa commented on June 25, 2024

yeah, my mistake. I flatten single elements:
https://github.com/Urucas/slackin/blob/master/lib/locale/de.js#L20

from slackin.

vrunoa avatar vrunoa commented on June 25, 2024

@rauchg your idea is to change the en.js from

export default function en() {
  return {
    join: function(room) {
      return ['Join ', dom('b', room), ' on Slack'];
    },
    state: function(active, total) {
      return active ? [
        dom('b.active', active), ' users online now of ',
        dom('b.total', total), ' registered.'
      ] : 
        dom('b.total', total), ' users are registered so far.'

    },
    getinvite: function() {
      return dom('button.loading', 'Get my Invite');
    },
    powered: function() {
      return 'powered by ';  
    }
  }
}

to this:

export function join(room) {
  return ['Join ', dom('b', room), ' on Slack'];
};
export function state(active, total) {
  return active ? [
    dom('b.active', active), ' users online now of ',
    dom('b.total', total), ' registered.'
  ] : 
    dom('b.total', total), ' users are registered so far.'
};
export function getinvite {
  return dom('button.loading', 'Get my Invite');
};
export function powered() {
  return 'powered by ';  
}

right? Or i'm misunderstanding ?

from slackin.

rauchg avatar rauchg commented on June 25, 2024

Right. Mostly I was curious about why you went with the other way. Which I think is valid, but still curious if you thought it had any particular advantages for this usecase.

from slackin.

vrunoa avatar vrunoa commented on June 25, 2024

To be honest, I went the other because I was misunderstanding es6 export,import.

I thought this way I would have to use

import * from 'locale/en'

instead of using

import en from 'locale/'

and import every method in the en module.
My mistake, thanks for your correction.

I just updated the translations modules en, de, es and the test. It's working. 😃

Let me know and I create a PR.

from slackin.

rauchg avatar rauchg commented on June 25, 2024

import * as en from locale/en should work in that case.
Likewise, you can have locale/index exporting the known languages:

import es from './es';
export { es }

from slackin.

vrunoa avatar vrunoa commented on June 25, 2024

Thanks for the tips @rauchg

from slackin.

rauchg avatar rauchg commented on June 25, 2024

While we're on the subject, the import syntax is extremely confusing.

import x from y; doesn't mean import x from y <!>, it means, import y('s default export), and call it x.

(╯°□°)╯︵ ┻━┻

from slackin.

vrunoa avatar vrunoa commented on June 25, 2024

ooh. Now I fully understand. \o/

from slackin.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.