Categories
Vue

Creating Multilingual Apps with vue-i18n

Vue.js is an easy to use web app framework that we can use to develop interactive front end apps.

In this article, we’ll look at how to create multilingual Vue apps with vue-i18n.

Getting Started

To get started, we install the package by writing:

npm i vue-i18n

Then we can write:

main.js

import Vue from "vue";
import App from "./App.vue";
import VueI18n from "vue-i18n";

Vue.use(VueI18n);

const messages = {
  en: {
    message: {
      hello: "hello"
    }
  },
  fr: {
    message: {
      hello: "bonjour"
    }
  }
};

const i18n = new VueI18n({
  locale: "fr",
  messages
});

Vue.config.productionTip = false;
new Vue({
  i18n,
  render: h => h(App)
}).$mount("#app");

And we can display the translation by writing:

<template>
  <div id="app">
    <p>{{ $t("message.hello") }}</p>
  </div>
</template>

<script>
export default {
  name: "App"
};
</script>

Formatting

We can interpolate expression in our messages by writing:

import Vue from "vue";
import App from "./App.vue";
import VueI18n from "vue-i18n";

Vue.use(VueI18n);

const messages = {
  en: {
    message: {
      hello: "{msg} world"
    }
  },
  fr: {
    message: {
      hello: "bonjour"
    }
  }
};

const i18n = new VueI18n({
  locale: "en",
  messages
});

Vue.config.productionTip = false;
new Vue({
  i18n,
  render: h => h(App)
}).$mount("#app");

And in our component, we can write:

<template>
  <div id="app">
    <p>{{ $t('message.hello', { msg: 'hello' })  }}</p>
  </div>
</template>

<script>
export default {
  name: "App"
};
</script>

Then we get hello world displayed on screen.

List Formatting

We can format lists with vue-i18n.

For example, we can write:

const messages = {
  en: {
    message: {
      hello: "{0} world"
    }
  },
  fr: {
    message: {
      hello: "bonjour"
    }
  }
};

And we can write:

<template>
  <div id="app">
    <p>{{ $t('message.hello', ['hi']) }}</p>
  </div>
</template>

<script>
export default {
  name: "App"
};
</script>

to display hello world .

We can also use an array-like object instead of an array:

<template>
  <div id="app">
    <p>{{ $t('message.hello', {'0': 'hi'}) }}</p>
  </div>
</template>

<script>
export default {
  name: "App"
};
</script>

And we get the same thing.

Ruby on Rails Message Format

The placeholder can also be written in Ruby on Rails format.

For instance, we can write:

const messages = {
  en: {
    message: {
      hello: "%{msg} world"
    }
  },
  fr: {
    message: {
      hello: "bonjour"
    }
  }
};

And we write:

<template>
  <div id="app">
    <p>{{ $t('message.hello', {msg: 'hi'}) }}</p>
  </div>
</template>

<script>
export default {
  name: "App"
};
</script>

Custom Formatter

We can add a custom formatter class:

class CustomFormatter {
  constructor (options) {
    // ...
  }

 interpolate (message, values) {
    return ['resolved message string']
  }
}

Then we can set it in the message that we pass into the VueI18n constructor:

const i18n = new VueI18n({
  locale: 'en',
  formatter: new CustomFormatter(),
  messages: {
    en: {
      // ...
    },
    // ...
  }
})

We just set the formatter property of the object we pass into the constructor.

Pluralization

vue-18n supports pluralization.

To add single and plural words to messages , we add the words to a string separated by the | character.

For instance, we can write:

import Vue from "vue";
import App from "./App.vue";
import VueI18n from "vue-i18n";

Vue.use(VueI18n);

const messages = {
  en: {
    apple: "apple | apples",
    orange: "no oranges | one orange | {count} oranges"
  }
};

const i18n = new VueI18n({
  locale: "en",
  messages
});

Vue.config.productionTip = false;
new Vue({
  i18n,
  render: h => h(App)
}).$mount("#app");

Then we write the following in our component:

<template>
  <div id="app">
    <p>{{ $tc('apple', 1) }}</p>
    <p>{{ $tc('apple', 2) }}</p>

    <p>{{ $tc('orange', 0) }}</p>
    <p>{{ $tc('orange', 1) }}</p>
    <p>{{ $tc('orange', 5, { count: 5 }) }}</p>
  </div>
</template>

<script>
export default {
  name: "App"
};
</script>

And we get:

apple

apples

no oranges

one orange

5 oranges

on the screen.

We used the $tc function instead of the $t function for regular translations.

The placeholder is in the braces.

DateTime Localization

Date and time can also be localized, we just have to pass in an object with the date formats we want to show.

To do that, we write:

import Vue from "vue";
import App from "./App.vue";
import VueI18n from "vue-i18n";

Vue.use(VueI18n);

const dateTimeFormats = {
  en: {
    short: {
      year: "numeric",
      month: "short",
      day: "numeric"
    },
    long: {
      year: "numeric",
      month: "short",
      day: "numeric",
      weekday: "short",
      hour: "numeric",
      minute: "numeric"
    }
  }
};

const i18n = new VueI18n({
  locale: "en",
  dateTimeFormats
});

Vue.config.productionTip = false;
new Vue({
  i18n,
  render: h => h(App)
}).$mount("#app");

Then we can use the $d function as follows:

<template>
  <div id="app">
    <p>{{ $d(new Date(), 'short') }}</p>
    <p>{{ $d(new Date(), 'long', 'en') }}</p>
  </div>
</template>

<script>
export default {
  name: "App"
};
</script>

We pass in the 'long' and 'short' format strings and optionally the language.

Conclusion

We can use vue-i18n to format localize our apps.

Text, single and plural words, and dates can be added for different locales.

Categories
JavaScript

Good Parts of JavaScript — Methods From the Standard Library

JavaScript is one of the most popular programming languages in the world. It can do a lot and have some features that are ahead of many other languages.

In this article, we’ll look at some useful array methods from the JavaScript standard library.

Array

The JavaScript standard library has many useful array methods.

array.unshift(item…)

The unshift adds items to the beginning of the array.

It returns the array’s new length.

For instance, we can write:

const a = ['a', 'b', 'c'];
const b = a.unshift('d');

Then a becomes [“d”, “a”, “b”, “c”] and b is 4.

Function

If we have to work with traditional functions, then these methods would help us.

function.apply(thisArg, argArray)

We can use apply to call a traditional function with a different value of this than what’s inside with an array of arguments.

For instance, we can write:

function foo(a, b) {
  console.log(`${this.value} ${a} ${b}`);
}

foo.apply({
  value: 'foo'
}, ['bar', 'baz']);

Then we get:

foo bar baz

from the console log output because this is:

{
  value: 'foo'
}

a is 'bar' and b is 'baz' .

Number

Various number methods also make our lives easier when we work with numbers.

number.toExponential(fractionDigits)

The toExponential method lets us convert numbers to exponential notation with the number of fractional digits after the decimal point.

The returned value is a string.

For instance, we can write:

console.log((Math.PI.toExponential(2)));

We get:

3.14e+0

from the console log output.

number.toFixed(fractionDigits)

The toFixed method returns a string representation of a number in decimal form.

It’ll have the number of digits after the decimal point as we specify them.

For instance, we can write:

console.log(Math.PI.toFixed(5));

And we get:

3.14159

from the console log.

number.toPrecision(precision)

The toPrecision method converts a number to a string in decimal form.

The precision parameter is optional and controls the number of digits of precision.

For instance, we can write:

console.log(Math.PI.toPrecision(5));

And get:

3.1416

number.toString(radix)

toString converts number to a string.

We can specify the optional radix parameter to control the base of the number.

radix should be between 2 and 36. The default radix is 10.

For instance, we can write:

console.log(Math.PI.toString(8));

to convert Math.PI to base 8. We get:

3.1103755242102643

Object

The Object.prototype has some useful methods that we can use.

object.hasOwnProperty(name)

hasOwnProperty lets us check if a property of an object is inherited or own property.

true is returned if name is an own property.

For instance, we can write:

const obj = {
  foo: 'bar'
};
const child = Object.create(obj);
console.log(child.hasOwnProperty('foo'));

Then we get false since foo is an inherited property of child .

RegExp

The RegExp constructor also comes with some useful methods for matching patterns.

regexp.exec(string)

The exec method finds all the matches of a regex pattern in a given string.

For instance, we can write:

console.log(/foo/g.exec('foo foo bar'));

Then we get the matches in an iterator.

regexp.test(string)

The test method is used for checking if a string matches the given regex.

For instance, we can write:

console.log(/foo/g.test('foo foo bar'));

And get true logged because 'foo' is in ‘foo foo bar’ .

String

Various string methods are also very useful for manipulating strings.

string.charAt(pos)

The charAt method returns the character at the given position.

For instance, we can write:

const name = 'joe';
const initial = name.charAt(0);

and get 'j' as the value of initial .

string.charCodeAt(pos)

charCodeAt is similar to charAt except that the integer representation of the code point of the character is returned instead of the character itself.

For instance, we can write:

const name = 'joe';
const code = name.charCodeAt(0);

Then we get code 106 for character 'j' .

If pos is less than 0 or bigger than or equal to string.length then NaN is returned.

string.concat(string…)

We can use the concat method to concatenate one or more strings together.

For instance, we can write:

console.log('foo'.concat('bar', 'baz'));

and get foobarbaz from the console log output.

Conclusion

There’re many array, strings, and regex methods that we can’t overlook.

They’re very useful and let us deal with any kind of data with ease.

Combining strings with concat is useful.

We can use the regex test method to check if a string match a regex pattern, and do much more.

Categories
JavaScript

Good Parts of JavaScript — Augmenting Types and More

JavaScript is one of the most popular programming languages in the world. It can do a lot and have some features that are ahead of many other languages.

In this article, we’ll look at ways to call functions and access arguments, ending the execution of functions, and augmenting built-in types.

Apply Invocation Pattern

We can use the function’s apply method to set the value this and pass in arguments.

For instance, we can write:

const array = [1, 2];
const sum = add.apply(null, array);

We set this to null and the arguments to the entries of array .

The apply method is only available in traditional functions.

Arrow function don’t bind to this , so it doesn’t have apply .

To set the value of this with apply and call a method, we can write:

const obj = {}

const obj2 = {}

function getValue(value) {
  this.value = value
  return this.value;
}

console.log(getValue.apply(obj, [1]));
console.log(getValue.apply(obj2, [2]));

In the code above, we have the getValue function.

In the last 2 lines, we set the value of this to obj and obj2 respectively.

Then we call them 1 or 2 respectively.

This way the first call returns 1 and the second returns 2.

Arguments

We can use the arguments object to access the arguments that are passed into a function.

This only works with traditional functions, so we can’t use it with arrow functions.

For instance, we can write:

const add = function() {
  let sum = 0;
  for (let i = 0; i < arguments.length; i++) {
    sum += arguments[i];
  }
  return sum;
};

Then we can call it by writing:

add(1, 2, 3, 4, 5);

to pass them in as arguments.

Then in add , we loop through the arguments object to get all the arguments.

arguments isn’t an array, but it has indexes and the length property.

Rest Parameters

The modern alternative is to use rest parameters.

We can rewrite the add function by writing:

const add = (...args) => {
  let sum = 0;
  for (const a of args) {
    sum += a;
  }
  return sum;
};

We call add the same way.

But we added a rest parameter args , which is an array of all the arguments passed in.

Then we used the for-of loop to loop through the items and add up the numbers.

Return

The return keyword is used to end the execution of a function.

We can use it anywhere.

This means we can create guard clauses with it. They are code that ends the function is something required by the function isn’t there.

A function always returns a value, if a return value isn’t specified, then undefined is returned.

If a function is run with a new prefix and we didn’t specify an explicit return statement.

Then this , which is the object created by the constructor, is returned.

Exceptions

JavaScript has an exception handling mechansim.

Exceptions are unusual things that interfere with the normal flow of a program.

When we run into something that causes issues, we may throw an exception.

The throw statement interrupts the execution of a function.

We can surround any code that throws an exception with a try-catch block.

For instance, we can write:

try {
  add(1, 2, 3);
} catch (e) {
  console.log(e);
}

In the code above, add may throw an exception, so we wrapped it around a try block.

This way, when an exception is thrown, the catch block will catch the exception.

Augmenting Types

Augmenting types are adding methods to built-in constructors.

We should do that by using creating a subclass of the built-in constructors.

To augment a built-in type, we can create a subclass by using the extends keyword.

This way, we don’t change the built-in prototypes directly, which isn’t a good idea because it adds unexpected methods that people don’t expect.

For instance, we can create a subclass of String as follows:

class FancyString extends String {
 greet(){
   console.log(`hi ${this}`)
  }
}

const str = new FancyString('foo');
str.greet()

In the code above, we created the FancyString class, which inherits all the members of the String constructor.

Inside it, we add a greet method.

Then we can use it as follows:

const str = new FancyString('foo');
str.greet();

We create a FancyString instance and called greet on it.

this would be 'foo' , so we ‘hi foo’ is logged.

Conclusion

With traditional functions, we can use the apply method to change the value of this inside a traditional function and pass in an array of arguments to call a function.

Functions can have code that throws exceptions, and we can use a try-catch block to catch the exceptions.

We can augment types by using the class syntax and the extends keyword.

Categories
JavaScript

Good Parts of JavaScript — Function Invocation

JavaScript is one of the most popular programming languages in the world. It can do a lot and have some features that are ahead of many other languages.

In this article, we’ll look at some good parts of JavaScript functions.

Function Invocation

Functions have to be invoked for them to do something.

They may or may not be called with arguments. In addition to arguments that we pass in, there’s so the this and arguments value.

this is the object that the function resides or the instance of the constructor.

It can also be the function that it’s in.

The invocation operator is a pair of parentheses with the arguments separated by commas.

If there are too many arguments, the extra arguments are ignored.

This means that the signature of the function doesn’t have to match the arguments that are passed in.

There’s no type checking on argument values. This means that we can pass on anything.

Therefore, we should be careful when we’re passing in parameters to a function.

The Method Invocation Pattern

When a function is stored in an object, then the function is called a method.

When a method is invoked, this is bound to the object.

We can call a method by using the dot notation or bracket notation.

For instance, given the following object:

const obj = {
  value: 0,
  increment(val) {
    this.value += val;
  }
};

We can write the following:

obj.increment(2);

Then obj.value will be increased by 2 since this is set to obj in the increment method.

Methods that are in the object context of this are called public methods.

Function Invocation Pattern

JavaScript functions can be standalone functions.

For instance, we can create a function as follows:

const add = (a, b) => {
  return a + b;
}

Then we can call it as follows:

add(1, 2);

Traditional functions are bound to the global object, so this of a traditional function at the top level would be window in the browser.

However, arrow functions aren’t bound to this , so it’ll be undefined at the top level.

Therefore, we should use arrow functions as much as we can so that the value of this would be the same as what it is on the outside.

So we can write:

const obj = {
  val: 0,
  foo() {
    const helper = () => {
      this.val = 1;
    }
  }
}

to access this.val in a nested function.

this is still obj within the helper arrow function.

If we use a traditional to define helper , we can write:

const obj = {
  val: 0,
  foo() {
    const that = this;
    const helper = function() {
      that.val = 1;
    }
  }
}

We’ve to assign this to that so that this will be obj rather than helper .

Constructor Invocation Pattern

JavaScript is a prototypical inheritance language. Objects can inherit properties directly from other objects.

There are no classes in JavaScript. Classes are just syntactic sugar.

JavaScript’s prototypical inheritance will confuse people coming from languages with classical inheritance.

JavaScript has the new operator like other object-oriented languages.

However, it’s just used to call a function in a special way.

It creates a hidden link to the value of a constructor’sprototype member.

The new prefix modifies the behavior of the return statement.

Functions that are used with the new prefix are called constructors.

They’re kept in variables with a capitalized name.

If we invoke a constructor without the new prefix, we would have issues with the value of this being not what we expect.

We don’t get any warnings about this other than unexpected behavior, so we need to be careful.

To define a constructor function, we can write:

const Foo = function(string) {
  this.status = string;
};

The code above is the most basic constructor function. It just takes a string parameter and set string to this.status .

Then we can invoke it by writing:

const foo = new Foo('good');

Then foo.status is 'good' .

To add an instance method, we can write:

const Foo = function(string) {
  this.status = string;
};

Foo.prototype.getStatus = function() {
  return this.status;
};

then we call foo.getStatus() to return 'good' .

Conclusion

There are multiple ways to call functions in JavaScript.

Methods are functions that are in an object. We can call it with the dot or bracket notation.

Also, we can create a constructor by using the function keyword.

To define instance methods, we can add it in the prototype property of the function.

Categories
JavaScript

Good Parts of JavaScript — Array Methods From the Standard Library

JavaScript is one of the most popular programming languages in the world. It can do a lot and have some features that are ahead of many other languages.

In this article, we’ll look at some useful array methods from the JavaScript standard library.

Array

The JavaScript standard library has many useful array methods.

array.concat(item…)

The concat method is used to combine multiple arrays into one or make a shallow copy of an array.

For instance, we can write:

const a = [1, 2, 3];
const b = [4, 5, 6];
const c = a.concat(b, 7);

We can pass in array or values into an array.

And we get [1, 2, 3, 4, 5, 6, 7] as the value of c .

array.join(separator)

The join method is used to combine all the entries of an array into a string with a given separator between them.

For instance, we can write:

const a = [1, 2, 3];
const b = a.join(',');

Then b is '1,2,3' .

array.pop( )

pop lets us remove the last element from an array and return the removed item.

For instance, we can write:

const a = [1, 2, 3];
const b = a.pop();

We get 3 for b because we removed 3 from a .

[1, 2] is the value for a .

array.push(item…)

push lets us add one or more items to the end of the array.

The new length of the array is returned.

For instance, we can write:

const a = [1, 2, 3];
const b = a.push(4, 5);

We get that a is [1, 2, 3, 4, 5] and b is 5.

array.reverse( )

The reverse method reverses the array entries within an array and returns the new array with the entries reversed.

For instance, we can write:

const a = [1, 2, 3];
const b = a.reverse();

Then we get that b is [3, 2, 1] .

array.shift( )

shift removes the first element of an array and returns it.

If the array is empty, then undefined is returned.

shift is usually a lot slower than pop .

For instance, we can write:

const a = [1, 2, 3];
const b = a.shift();

The b is 1 and a is [2, 3] .

array.slice(start,end)

slice returns a shallow copy of an array. While the slice operator is being done, we can modify it by specifying the start and end indexes.

For instance, we can write:

const a = [1, 2, 3];
const b = a.slice(0, 1);

Then we get that b is [1] since we return the portion of a between index 0 and 1.

array.sort(comparefn)

The sort method lets us sort the contents of an array in place.

By default, it assumes the elements that are sorted are strings.

It doesn’t test the content of the elements before sorting them.

All it does is convert them to strings then sort them.

Therefore, if we write:

const a = [3, 15, 16, 23];
a.sort();

We get the new value of a is:

[15, 16, 23, 3]

which is probably not what we want.

sort takes a callback which we can use to sort items our way.

So we can pass in a callback to sort numbers properly.

If we want to sort numbers in ascending order, we can write:

const a = [3, 15, 16, 23];
a.sort((a, b) => a - b);

Then a becomes [3, 15, 16, 23] .

The callback takes 2 parameters, which are 2 numbers to compare, and a negative number is returned if we want the first to come after the second.

And positive if we want to reverse the order.

0 should be returned by the callback if we want the order to stay the same.

array.splice(start, deleteCount, item…)

splice can be used to remove elements from an array and also replace the slow with new items.

For instance, we can write:

const a = ['a', 'b', 'c', 'd', 'e'];
const b = a.splice(1, 1);

The code above removes one element starting with index 1.

So 'b' is removed and returned by splice . So b is [“b”] .

a is [“a”, “c”, “d”, “e”] .

We can replace 'b' with 'f' and 'g' by writing:

const b = a.splice(1, 1, 'f', 'g');

and we get a is [“a”, “f”, “g”, “c”, “d”, “e”] while b is the same.

Conclusion

There’re many useful array methods that make our lives much easier when we have to work with JavaScript arrays.

We should use them instead of loops.