<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Thomas Lombart</title>
    <description>The latest articles on DEV Community by Thomas Lombart (@thomaslombart).</description>
    <link>https://dev.to/thomaslombart</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F173653%2F10711277-ce57-4470-8caa-35292bf0b32c.jpg</url>
      <title>DEV Community: Thomas Lombart</title>
      <link>https://dev.to/thomaslombart</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/thomaslombart"/>
    <language>en</language>
    <item>
      <title>How to Make Slack Feel Calm and Productive</title>
      <dc:creator>Thomas Lombart</dc:creator>
      <pubDate>Mon, 03 Jan 2022 06:58:27 +0000</pubDate>
      <link>https://dev.to/thomaslombart/how-to-make-slack-feel-calm-and-productive-2n34</link>
      <guid>https://dev.to/thomaslombart/how-to-make-slack-feel-calm-and-productive-2n34</guid>
      <description>&lt;p&gt;Slack is one of the most popular communication tools in tech. As a developer, I use it every day to collaborate with my peers. This tool is packed with lots of features and does its job: making communication easy in a company or community. But there's one downside: Slack is designed to be an instant communication tool. And that is a disaster when you want to focus. You get mentioned in channels, you receive many direct messages, you catch up on threads, you see red dots everywhere. In the end, you are addicted to Slack and you end up with the bad habit of clicking on notifications or checking Slack every five minutes.&lt;/p&gt;

&lt;p&gt;Don't worry, we've all been there before. There are lots of ways to make Slack calmer and we'll discover them right away. Let's get your focus back.&lt;/p&gt;

&lt;h3&gt;
  
  
  Get rid of notifications
&lt;/h3&gt;

&lt;p&gt;Yeah, that one is obvious. If you're annoyed by the Slack notification sound, well get rid of notifications. They're a major source of distractions, which we can't afford as knowledge workers. You don't need to have a notification every time someone mentions you or uses a &lt;code&gt;@here&lt;/code&gt; though the message is not that important.&lt;/p&gt;

&lt;h3&gt;
  
  
  Leave or mute useless channels
&lt;/h3&gt;

&lt;p&gt;Maybe you're in of these channels that get lots of messages though you're inactive. Or maybe you joined a channel just for a one-time question or message.&lt;/p&gt;

&lt;p&gt;Don't bother staying in these channels if you don't find any important messages and leave them. If leaving them sounds too extreme, you can also just mute them. The goal is to focus on channels that matter to you, not to know everything happening in your Slack workspace.&lt;/p&gt;

&lt;h3&gt;
  
  
  Quit Slack when focusing
&lt;/h3&gt;

&lt;p&gt;Developers make work happen by building, fixing, or shipping stuff. And this happens mostly during focus, not in Slack. A simple solution to get your focus back is to quit Slack when you need to focus. That way, you're 100% sure you won't get disturbed by notifications or unread messages.&lt;/p&gt;

&lt;p&gt;It can be disturbing at first since Slack excels at making you feel FOMO. But you get used to it. If you're too stressed about it, start small. Don't quit Slack for 2 hours, but 15 minutes. Then, increase the duration and adjust it to the amount of time needed to focus. Yes, you won't answer people but they often adjust to your response time to a certain extent.&lt;/p&gt;

&lt;p&gt;If you don't feel comfortable quitting Slack, you can turn on &lt;strong&gt;Do Not Disturb&lt;/strong&gt; (DND) mode by clicking on your profile and then &lt;strong&gt;Pause notifications.&lt;/strong&gt; That would work as well. As a personal note, I prefer quitting Slack so I'm not tempted to switch to it during my focus periods.&lt;/p&gt;

&lt;p&gt;Note: make sure the persons you're working with are OK with this, though. We don't all have the chance to work in an environment of trust. If it's impossible for you, use the &lt;strong&gt;Do Not Disturb&lt;/strong&gt; mode.&lt;/p&gt;

&lt;h2&gt;
  
  
  Customize Slack
&lt;/h2&gt;

&lt;p&gt;Slack has lots of customization options and that's a good thing to reduce the noise you get by default.&lt;/p&gt;

&lt;h3&gt;
  
  
  Group channels into sections
&lt;/h3&gt;

&lt;p&gt;If there are too many channels and you get lost in them, you can use sections for a better organization. Here are two possible organizations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Group channels by category: team, company, skills (front-end, back-end, product for example)&lt;/li&gt;
&lt;li&gt;Group channels by priority: high priority, medium priority, low priority.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I like to use the latter organization. I have a section called &lt;strong&gt;Priority&lt;/strong&gt; for all important channels, another section called &lt;strong&gt;End of day&lt;/strong&gt; for channels I want to check at... the end of the day. I don't check often the rest of the channels unless I'm looking for something really specific.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd00s8mc7fbd03q8m1ojs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd00s8mc7fbd03q8m1ojs.png" alt="Screenshot of my Slack workspace's organization" width="514" height="726"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This feature is only for &lt;a href="https://slack.com/intl/en-gb/help/articles/360043207674-Organise-your-sidebar-with-customised-sections" rel="noopener noreferrer"&gt;Slack paid subscriptions&lt;/a&gt;. You may not be able to use it depending on your workspace.&lt;/p&gt;

&lt;p&gt;Note that you can also show only unread conversations for certain sections. That way, you have a clearer view of channels and messages to catch up with when you come back on Slack after a focus session.&lt;/p&gt;

&lt;h3&gt;
  
  
  Change the colors
&lt;/h3&gt;

&lt;p&gt;I find Slack's default UI to be aggressive on the eye. Luckily, it's possible to change the colors by going to the preferences in the theme section:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6vb8pbz7myr56kct9271.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6vb8pbz7myr56kct9271.png" alt="Screenshot of the themes preferences in Slack" width="800" height="456"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That is perfect, especially for one thing: the mention badge. You see, I'm the kind of person who doesn't like having unread notifications. And this red badge makes me want to click it every time I see it. Reducing the contrast makes them less visible and makes me more OK in not clicking it directly. Here's a comparison:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs0c9u4t2oikxk0lixmbb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs0c9u4t2oikxk0lixmbb.png" alt="Screenshot of the default mentions in Slack" width="520" height="322"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After customizing the mention badge:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1gsymvzve3a53tr9jzkd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1gsymvzve3a53tr9jzkd.png" alt="Screenshot of the customized mentions in Slack" width="522" height="306"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Communicate better
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Use threads and reactions
&lt;/h3&gt;

&lt;p&gt;Slack's channels are sometimes used as an instant conversation between channel members. That's the perfect recipe to add noise to the channel and make information harder to find. For that reason, it's better to use threads. This makes topics more scannable and people who are not interested in the original message don't have to read unwanted messages. Nice and clean.&lt;/p&gt;

&lt;p&gt;Note: threads are great to reduce channel messages. But when you're mentioned in one, you get notifications for the upcoming replies. Like channels, you can &lt;strong&gt;mute&lt;/strong&gt; threads. Think of it in case of heated discussions.&lt;/p&gt;

&lt;p&gt;Slack has another neat feature to reduce noise: reactions. They're great for saving you all kinds of messages and making the workspace calmer. So, instead of saying something like "OK for me", you can just react with a checkmark (✅). Another example, instead of saying "I’m taking a look", you can add the eyes emoji (👀)&lt;/p&gt;

&lt;h3&gt;
  
  
  Write longer messages
&lt;/h3&gt;

&lt;p&gt;We've seen so far how to make Slack calm with some of their tools. We can go further. Indeed, a big part of the noise created comes from the way you communicate with your teammates.&lt;/p&gt;

&lt;p&gt;It's common to receive messages from people who type as they think, the kind of person who makes your mention badge go from 1 to 9+ in the blink of an eye.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzjnxn8jysnvhf8so3zbx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzjnxn8jysnvhf8so3zbx.png" alt="Screenshot of someone spamming messages" width="800" height="412"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can't blame them after all! Slack has decided to use a one-line input instead of a multiline one for writing messages. No wonder everyone thinks in terms of one-line messages!&lt;/p&gt;

&lt;p&gt;Take instead the habit of writing longer, cleaner messages. It doesn't mean that you need to write great walls of text, though. You want to aim for a message that goes straight to the point and gives all the required information to reduce back and forth.&lt;/p&gt;

&lt;p&gt;A good technique to write a clean yet detailed message is to use the BLUF (Bottom Line Up Front) approach: put the critical information at the beginning, then follow with the context and details.&lt;/p&gt;

&lt;p&gt;Let's take an example. You encounter a bug that you don't know how to fix. So, you write a message asking for help:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Hey everyone! I worked on project X this morning and something surprised me while I was testing stuff. I went to this page, I clicked on this button and I got an error. I don't understand why it happens since I can't reproduce it in my local environment. My guess is that maybe something happens during the build but I'm not entirely sure of that. Can someone help me? It would be greatly appreciated!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As you can see, it's hard to find the message's purpose and details. Let's take the BLUF approach to make it clearer:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Can someone help me with a bug I can't reproduce locally happening on this page?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I worked on project X this morning and I found a bug happening on this page when clicking on that button. I haven't been able to reproduce it in my local environment. I guess something goes wrong during the build, but I'm not entirely sure of that.&lt;/p&gt;

&lt;p&gt;I'm available for a pair-programming session this morning from 10 AM to 11 AM if someone's up for the challenge.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now, we directly get what's the person asking which is better to make a channel more scannable.&lt;/p&gt;

&lt;p&gt;Writing better is a large topic. Instead of making this article way longer than it needs to be, here's a resource I highly recommend on how to write better at work: &lt;a href="https://blog.doist.com/business-writing/" rel="noopener noreferrer"&gt;How to Write For the Way Your Coworkers Actually Read&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Record videos
&lt;/h3&gt;

&lt;p&gt;Sometimes, it's hard to explain things by writing them. Maybe you need to support your message with images or demos, or maybe it's just a complex topic that can be hard to deconstruct. In this case, why not send async videos? They're perfect for these use-cases and can even spare you a few meetings. In case you're wondering, Slack has a built-in tool to send videos:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhzxv8c7is61qzf26s8yj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhzxv8c7is61qzf26s8yj.png" alt="Screenshot of Slack's built-in tool to send videos" width="800" height="210"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You're not limited to Slack only. There are other great apps to do recordings like &lt;a href="https://www.loom.com/" rel="noopener noreferrer"&gt;Loom&lt;/a&gt;, &lt;a href="https://cleanshot.com/" rel="noopener noreferrer"&gt;CleanShot&lt;/a&gt;, or simply your OS's built-in tool.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use a Slack status
&lt;/h3&gt;

&lt;p&gt;People are more likely to send you messages if you're marked as available. Think of using Slack statuses so that others know what you're up to. This has two benefits:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Maybe, they'll get back to you later when you'll be available for chatting.&lt;/li&gt;
&lt;li&gt;They'll know what you're doing and see that you have a good reason for not answering.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A nice integration you can put into Slack is the &lt;a href="https://slack.com/apps/ADZ494LHY-google-calendar?tab=more_info" rel="noopener noreferrer"&gt;Google Calendar app&lt;/a&gt; if you use it. This app syncs your meetings with your status so that others know when you're in a meeting or not. Handy!&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Sure, Slack is an instant messaging tool at its core but it's possible to reduce all the noise you get: by controlling your notifications, customizing Slack, or simply writing with an asynchronous-first mindset. Hopefully, these tips will make your Slack workspace a more focused place.&lt;/p&gt;

</description>
      <category>productivity</category>
    </item>
    <item>
      <title>Reverse-Engineering Airbnb’s Internationalization Library</title>
      <dc:creator>Thomas Lombart</dc:creator>
      <pubDate>Fri, 26 Nov 2021 19:28:14 +0000</pubDate>
      <link>https://dev.to/thomaslombart/reverse-engineering-airbnbs-internationalization-library-9c</link>
      <guid>https://dev.to/thomaslombart/reverse-engineering-airbnbs-internationalization-library-9c</guid>
      <description>&lt;p&gt;&lt;em&gt;This post has originally been written in 2019. I wanted to migrate it to DEV.to so you may stumble upon outdated things 😊&lt;/em&gt; &lt;/p&gt;

&lt;p&gt;Curiosity is one of the most essential developer's assets. By being curious and experimenting with things, you make sure you're continually learning and upgrading your skills. A while ago, I had to implement internationalization for an app I was working on.  I chose to use &lt;a href="http://airbnb.io/polyglot.js/" rel="noopener noreferrer"&gt;Polyglot&lt;/a&gt; because of its simplicity. It's also created by Airbnb, a company with many great &lt;a href="https://airbnb.io/projects/" rel="noopener noreferrer"&gt;open sources libraries&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;When I used Polyglot, I wondered what was going on under the hood. So I decided to do a little bit of reverse-engineering by diving into the source code. And here I am, sharing with you what I've learned along the way.&lt;/p&gt;

&lt;p&gt;You'll find many code snippets below. Most of them come from the &lt;a href="https://github.com/airbnb/polyglot.js/blob/master/index.js" rel="noopener noreferrer"&gt;source code of Polyglot&lt;/a&gt; itself. This article aims to give you more explanations about that code, its purpose, and its use.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recap about the library
&lt;/h2&gt;

&lt;p&gt;But first, let's do a recap about the library. Basically, Polyglot handles the internationalization of your app including &lt;strong&gt;interpolation&lt;/strong&gt; and &lt;strong&gt;pluralization&lt;/strong&gt;. You give it a set of translated phrases and you retrieve the ones you want using a special function called &lt;code&gt;t&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;polyglot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Polyglot&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;phrases&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;morning&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Morning&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;login&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Login&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;register&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Register&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;polyglot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;t&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hello&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Hello&lt;/span&gt;
&lt;span class="nx"&gt;polyglot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;t&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;morning&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Morning&lt;/span&gt;
&lt;span class="nx"&gt;polyglot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;t&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;auth.login&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Login&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice how Polyglot handles &lt;strong&gt;nested objects.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you want to add more phrases to the Polyglot instance, you can use the &lt;code&gt;extend&lt;/code&gt; method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;Polyglot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;bye&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Bye!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Polyglot supports &lt;strong&gt;interpolation&lt;/strong&gt;. Roughly speaking, it consists in replacing some placeholders in your phrase by a real value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;polyglot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;welcome&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Welcome %{name}&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;polyglot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;t&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;welcome&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Thomas&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt; &lt;span class="c1"&gt;// Welcome Thomas&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you don't provide one of the interpolation value, Polyglot will return your placeholder as-is. It can be useful if you want to do partial interpolation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;Polyglot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;My name is %{name}. I love %{hobby}!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;polyglot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;t&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Thomas&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt; &lt;span class="c1"&gt;// My name is Thomas. I love %{hobby}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also provide your own interpolation syntax:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;polyglot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Polyglot&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;interpolation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;prefix&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;{{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;suffix&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;}}&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;polyglot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;city&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;You live in {{city}}&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;polyglot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;t&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;city&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;city&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;London&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt; &lt;span class="c1"&gt;// You live in London&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, Polyglot handles pluralization, that is to say, express a sentence in the plural form. To make it work properly, Polyglot needs a locale (which is &lt;code&gt;en&lt;/code&gt; by default):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;polyglot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;locale&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// 'en'&lt;/span&gt;
&lt;span class="nx"&gt;polyglot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;thing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;There is %{smart_count} thing |||| There are %{smart_count} things&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;polyglot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;t&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;thing&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;smart_count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt; &lt;span class="c1"&gt;// There is 1 thing&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Giving a number as a second argument also works:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;Polyglot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;t&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;thing&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// There are 4 things&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you need to set the locale, you have two choices:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Call the &lt;code&gt;locale&lt;/code&gt; method with its corresponding code&lt;/li&gt;
&lt;li&gt;Provide the locale during the instantiation
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;polyglot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;locale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fr&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// OR&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;polyglot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Polyglot&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;locale&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fr&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What's great is that Polyglot supports many locales, dozens of locales!&lt;/p&gt;

&lt;p&gt;And then the less-used features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;unset&lt;/code&gt; to remove a key from Polyglot's phrases&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;clear&lt;/code&gt; to remove all the phrases from the Polyglot instance&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;replace&lt;/code&gt; to replace the current phrases with others&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;has&lt;/code&gt; to check if a translation exists for a given key
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;polyglot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;unset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hello&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;polyglot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;unset&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;register&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Register&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;polyglot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hey!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;bye&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Bye-bye&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;polyglot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;clear&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;polyglot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;has&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hello&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You may think that the translation itself is easy to do. In fact, it's just returning a value of an object based on a key. But what about nested key objects? The interpolation feature? Or the pluralization? And handling the pluralization for all the locales? 🤔&lt;/p&gt;

&lt;p&gt;Don't worry, we'll figure it out right away.&lt;/p&gt;

&lt;h2&gt;
  
  
  Translate a simple phrase
&lt;/h2&gt;

&lt;p&gt;Let's start with the simplest feature: translate a simple phrase. It's as easy as getting a key from an object. Internally, when you create an instance of Polyglot, an empty &lt;code&gt;phrases&lt;/code&gt; object is created. You can then extend it by providing some phrases in the &lt;code&gt;options&lt;/code&gt; object:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Polyglot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;opts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;phrases&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;phrases&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;{});&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We instanciate Polyglot like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;polyglot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Polyglot&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// phrases -&amp;gt; {}&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;polyglot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Polyglot&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;phrases&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt; &lt;span class="c1"&gt;// extend({hello: 'Hello'}) is called&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Polyglot makes use of &lt;strong&gt;short-circuit evaluation&lt;/strong&gt;. This complicated term means JavaScript takes advantage of logical operators such as &lt;code&gt;||&lt;/code&gt; (OR) to evaluate just what's necessary. Thus, if &lt;code&gt;options&lt;/code&gt; is &lt;code&gt;undefined&lt;/code&gt; or &lt;code&gt;null&lt;/code&gt;, JavaScript will assign &lt;code&gt;{}&lt;/code&gt; to &lt;code&gt;opts&lt;/code&gt; as the first operand evaluates to false. But if &lt;code&gt;options&lt;/code&gt; is set, it won't even look at the rest of the expression and assign &lt;code&gt;options&lt;/code&gt; to &lt;code&gt;opts&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Polyglot uses &lt;code&gt;extend&lt;/code&gt; to map a given key to a given phrase in its internal &lt;code&gt;phrases&lt;/code&gt; object. We'll come back to it in a few moments.&lt;/p&gt;

&lt;p&gt;Other things happen when you instanciate Polyglot including this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Polyglot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;opts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;currentLocale&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;locale&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;en&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tokenRegex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;constructTokenRegex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;interpolation&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;currentLocale&lt;/code&gt; is set to a given locale or &lt;code&gt;en&lt;/code&gt; and a mysterious &lt;code&gt;tokenRegex&lt;/code&gt; is created. These properties are important for interpolation and pluralization.&lt;/p&gt;

&lt;p&gt;Then, when we'll call &lt;code&gt;t&lt;/code&gt; with a given key, Polyglot will search its associated value in the internal &lt;code&gt;phrases&lt;/code&gt; object. Once found, it will apply to the phrase some transformations (interpolation and pluralization) and return it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;Polyglot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;phrase&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;opts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;phrases&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;phrase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;phrases&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;phrase&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;transformPhrase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;phrase&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;currentLocale&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tokenRegex&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;"What an odd way to declare a method"&lt;/em&gt;, you might say. Why not simply use the &lt;code&gt;class&lt;/code&gt; keyword?&lt;/p&gt;

&lt;p&gt;Because JavaScript is continuously evolving. When this library was written, there were no such things as classes (as well as &lt;code&gt;const&lt;/code&gt; and &lt;code&gt;let&lt;/code&gt;). It was only introduced in 2015. So we had to create classes by using &lt;strong&gt;constructor functions&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;But, functions being functions, it's not efficient to put all methods inside a constructor function. That would mean that every function inside the constructor function would be created at each instantiation!&lt;/p&gt;

&lt;p&gt;That's why there is a &lt;code&gt;prototype&lt;/code&gt; property inside every function: &lt;strong&gt;by putting a method in the &lt;code&gt;prototype&lt;/code&gt; property, you share it across all instances of your function.&lt;/strong&gt; Check out &lt;a href="https://tylermcginnis.com/beginners-guide-to-javascript-prototype/" rel="noopener noreferrer"&gt;this resource&lt;/a&gt; to learn more about prototypes.&lt;/p&gt;

&lt;p&gt;By the way, classes in JavaScript are also &lt;strong&gt;constructor functions.&lt;/strong&gt; Go ahead and define a &lt;code&gt;class&lt;/code&gt;. You'll see its type is &lt;code&gt;Function&lt;/code&gt;. Interesting, isn't it?&lt;/p&gt;

&lt;h2&gt;
  
  
  Extend
&lt;/h2&gt;

&lt;p&gt;The most attentive of you will think &lt;em&gt;"But what if our &lt;code&gt;phrases&lt;/code&gt; object has inner objects? I don't see how &lt;code&gt;t&lt;/code&gt; handles the nested objects? It only transforms the phrase if the type of the phrase is a string, right?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That's a legit question. As said in the recap, Polyglot handles nested phrases objects. Under the hood, It uses the &lt;code&gt;extend&lt;/code&gt; method to add new phrases to the instance. This method recursively processes all the keys in the object passed as an argument and puts them at the root level of the internal &lt;code&gt;phrases&lt;/code&gt; object. Each nested key is concatenated with the one that's one level above it using the dot notation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;forEach&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;for-each&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// ...&lt;/span&gt;

&lt;span class="nx"&gt;Polyglot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;extend&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;morePhrases&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;prefix&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;morePhrases&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;phrase&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;prefixedKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;prefix&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;prefix&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;phrase&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;object&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;phrase&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;prefixedKey&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;phrases&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;prefixedKey&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;phrase&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: Polyglot uses a package called &lt;a href="https://github.com/Raynos/for-each" rel="noopener noreferrer"&gt;for-each&lt;/a&gt; to iterate over both objects and arrays. It acts as a polyfill so that Polyglot doesn't require added methods like &lt;code&gt;Array.prototype.forEach&lt;/code&gt;. Suppose you wonder what the third &lt;code&gt;this&lt;/code&gt; argument passed to &lt;code&gt;forEach&lt;/code&gt; is. In that case, it allows specifying what is &lt;code&gt;this&lt;/code&gt; in the callback function (the second argument). In our case, &lt;code&gt;this&lt;/code&gt; refers to an instance of Polyglot.&lt;/p&gt;

&lt;p&gt;Let's see what happens if you call &lt;code&gt;extend&lt;/code&gt; like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;polyglot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;login&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Login&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;register&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Register&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;For the &lt;code&gt;hello&lt;/code&gt; key, &lt;code&gt;prefix&lt;/code&gt; will be &lt;code&gt;undefined&lt;/code&gt; so &lt;code&gt;prefixedKey = hello&lt;/code&gt;. The corresponding &lt;code&gt;phrase&lt;/code&gt; (&lt;code&gt;Hello&lt;/code&gt;) is a string, so we map &lt;code&gt;Hello&lt;/code&gt; to &lt;code&gt;hello&lt;/code&gt; in the internal &lt;code&gt;phrases&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For &lt;code&gt;auth&lt;/code&gt;, there is still no prefix, so &lt;code&gt;prefixedKey = auth&lt;/code&gt;. However, &lt;code&gt;phrase&lt;/code&gt; is an object, so we'll recursively call &lt;code&gt;extend&lt;/code&gt; with &lt;code&gt;phrase&lt;/code&gt; and &lt;code&gt;prefixedKey&lt;/code&gt;: &lt;code&gt;this.extend({ login: 'Login', register: 'Register' }, 'auth')&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For &lt;code&gt;login&lt;/code&gt;, there is a prefix which is &lt;code&gt;auth&lt;/code&gt;, so &lt;code&gt;prefixedKey = auth.login&lt;/code&gt;. Here &lt;code&gt;phrase&lt;/code&gt; is a string so we map &lt;code&gt;Login&lt;/code&gt; to &lt;code&gt;auth.login&lt;/code&gt; in the internal &lt;code&gt;phrases&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It's exactly the same behavior for &lt;code&gt;register&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That way, you make sure you traverse all your objects and map every key to a string value in the &lt;strong&gt;flattened&lt;/strong&gt; &lt;code&gt;phrases&lt;/code&gt; object. After calling &lt;code&gt;extend&lt;/code&gt;, your &lt;code&gt;phrases&lt;/code&gt; look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;login&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Login&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;register&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Register&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that &lt;code&gt;extend&lt;/code&gt; actually extends the &lt;code&gt;phrases&lt;/code&gt; object and &lt;strong&gt;doesn't replace it.&lt;/strong&gt; The only things that can be replaced are the conflicting keys. For example, if you call &lt;code&gt;extend&lt;/code&gt; with an object with a &lt;code&gt;hello&lt;/code&gt; key and that key already exists in &lt;code&gt;phrases&lt;/code&gt;, the old key will be replaced with the new one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Interpolation
&lt;/h2&gt;

&lt;p&gt;Let's come back to &lt;code&gt;transformPhrase&lt;/code&gt;, shall we? You may remember that we use it in the &lt;code&gt;t&lt;/code&gt; function to transform the phrase we get via our key:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;phrase&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;transformPhrase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;phrase&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;currentLocale&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tokenRegex&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We'll dive into its code to understand how one can build the interpolation feature.&lt;/p&gt;

&lt;p&gt;Here, the interpolation feature consists of replacing a generic word with another one in an object. What's great is that &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace" rel="noopener noreferrer"&gt;&lt;code&gt;String.prototype.replace&lt;/code&gt;&lt;/a&gt; does most of the work for us. Indeed, according to MDN, The &lt;code&gt;replace&lt;/code&gt; method returns a new string with some or all matches of a pattern replaced by a replacement. You just need to define a regular expression to capture what you need to replace and fetch the corresponding word in the &lt;code&gt;options&lt;/code&gt; object.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;has&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;has&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// ...&lt;/span&gt;

&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;replace&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// ...&lt;/span&gt;

&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;defaultTokenRegex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sr"&gt;/%&lt;/span&gt;&lt;span class="se"&gt;\{(&lt;/span&gt;&lt;span class="sr"&gt;.*&lt;/span&gt;&lt;span class="se"&gt;?)\}&lt;/span&gt;&lt;span class="sr"&gt;/g&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;transformPhrase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;phrase&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;substitutions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;locale&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;tokenRegex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;

  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;phrase&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;interpolationRegex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;tokenRegex&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;defaultTokenRegex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;substitutions&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;number&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;smart_count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;substitutions&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;substitutions&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;interpolationRegex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;expression&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;argument&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nf"&gt;has&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;argument&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;argument&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;expression&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;argument&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;dollarRegex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dollarBillsYall&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is how interpolation is done under the hood. Not less, not more. But you may be unfamiliar with things like &lt;code&gt;call&lt;/code&gt; or &lt;code&gt;String.prototype.replace&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Three essential things are done before calling &lt;code&gt;transformPhrase&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We &lt;strong&gt;require&lt;/strong&gt; the &lt;code&gt;has&lt;/code&gt; package which is a shortcut for &lt;code&gt;Object.prototype.hasOwnProperty.call&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;We &lt;strong&gt;cache&lt;/strong&gt; the &lt;code&gt;String.prototype.replace&lt;/code&gt; method.&lt;/li&gt;
&lt;li&gt;We create the &lt;code&gt;defaultRegexToken&lt;/code&gt; used to match the generic words in our phrases. Basically, this regex means &lt;em&gt;"match anything that is included inside &lt;code&gt;%{}&lt;/code&gt;"&lt;/em&gt;. Note that this regular expression is &lt;strong&gt;lazy&lt;/strong&gt; (&lt;code&gt;.*?&lt;/code&gt;) instead of &lt;strong&gt;greedy&lt;/strong&gt; (&lt;code&gt;.*&lt;/code&gt;). In other words, it means this regexp will capture the smallest group possible.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That being said, we can learn how &lt;code&gt;transformPhrase&lt;/code&gt; behaves.&lt;/p&gt;

&lt;p&gt;It takes four parameters: &lt;code&gt;phrase&lt;/code&gt;, &lt;code&gt;substitutions&lt;/code&gt;, &lt;code&gt;locale&lt;/code&gt; and &lt;code&gt;tokenRegex&lt;/code&gt;. We won't need &lt;code&gt;locale&lt;/code&gt; for now as it's needed for pluralization. Then, we assign to &lt;code&gt;interpolationRegex&lt;/code&gt; the regex that will be used for the replacements. It can be a custom regex (remember the mysterious &lt;code&gt;tokenRegex&lt;/code&gt; in the constructor?) or the &lt;code&gt;defaultTokenRegex&lt;/code&gt; explained above.&lt;/p&gt;

&lt;p&gt;Beforehand, we assign to &lt;code&gt;options&lt;/code&gt; the value of &lt;code&gt;substitutions&lt;/code&gt;. The &lt;code&gt;typeof&lt;/code&gt; check is done for pluralization. You don't have to care about it for now.&lt;/p&gt;

&lt;p&gt;Then, we actually replace the phrase using the regular expression. As the &lt;code&gt;replace&lt;/code&gt; function is cached, we need to use the &lt;code&gt;call&lt;/code&gt; method to specify on which string we want to invoke the &lt;code&gt;replace&lt;/code&gt; function, that is to say, &lt;code&gt;result&lt;/code&gt;. If using &lt;code&gt;call&lt;/code&gt; confuses you, it's the same as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;interpolationRegex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;expression&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;argument&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nf"&gt;has&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;argument&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;argument&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;expression&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;argument&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;dollarRegex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dollarBillsYall&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The second argument of &lt;code&gt;replace&lt;/code&gt; can either have the form of a string or a function. Here we use the function because we need to retrieve the eventual generic word's value in the options. This function will be run on every match with the following arguments:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;expression&lt;/code&gt;: refers to the match itself, &lt;code&gt;%{name}&lt;/code&gt; for example.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;argument&lt;/code&gt;: refers to the captured group (&lt;code&gt;(.*?)&lt;/code&gt;), that is to say, everything inside the interpolation syntax. By default, it is everything inside &lt;code&gt;%{}&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the captured string is a property of the &lt;code&gt;options&lt;/code&gt; object passed to &lt;code&gt;t&lt;/code&gt; and is different than &lt;code&gt;null&lt;/code&gt;, then we return its associated value otherwise, we return the expression itself. The returned value will be used as a replacement for the match.&lt;/p&gt;

&lt;p&gt;Let's apply it on an example to fully understand it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;Polyglot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hi, your name is %{name}. You are a %{job} and you like %{hobby}.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;polyglot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;t&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Thomas&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;hobby&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;traveling&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We assume we haven't provided any custom interpolation syntax to Polyglot. Then, &lt;code&gt;interpolationRegex&lt;/code&gt; is equal to &lt;code&gt;/%\{(.*?)\}/g&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We call &lt;code&gt;replace&lt;/code&gt; on the phrase &lt;code&gt;'Hi, your name is %{name}. You are a %{job} and you like %{hobby}.'&lt;/code&gt;. We'll have three matches: &lt;code&gt;%{name}&lt;/code&gt;, &lt;code&gt;%{job}&lt;/code&gt; and &lt;code&gt;%{hobby}&lt;/code&gt;. For every match, we run &lt;code&gt;replace&lt;/code&gt;'s callback function:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;expression&lt;/code&gt; = &lt;code&gt;%{name}&lt;/code&gt;, &lt;code&gt;argument&lt;/code&gt; = &lt;code&gt;name&lt;/code&gt;. Is &lt;code&gt;name&lt;/code&gt; in the options object? &lt;strong&gt;Yes&lt;/strong&gt;, then return the associated value: &lt;code&gt;Thomas&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;expression&lt;/code&gt; = &lt;code&gt;%{job}&lt;/code&gt;, &lt;code&gt;argument&lt;/code&gt; = &lt;code&gt;job&lt;/code&gt;. Is &lt;code&gt;job&lt;/code&gt; in the options object? No, return the expression: &lt;code&gt;%{job}&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;expression&lt;/code&gt; = &lt;code&gt;%{hobby}&lt;/code&gt;, &lt;code&gt;argument&lt;/code&gt; = &lt;code&gt;hobby&lt;/code&gt;. Is &lt;code&gt;hobby&lt;/code&gt; in the options object? Yes, then return the associated value: &lt;code&gt;traveling&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The result of the translation is: &lt;code&gt;Hi, your name is Thomas. You are a %{job}, and you like traveling.&lt;/code&gt; That's not rocket science, after all! 😉&lt;/p&gt;

&lt;h3&gt;
  
  
  Custom interpolation syntax
&lt;/h3&gt;

&lt;p&gt;We saw how to implement interpolation. Let's see how to customize the interpolation syntax. Indeed, Polyglot allows you to customize the prefix and the suffix so that you can use &lt;code&gt;{{name}}&lt;/code&gt; or &lt;code&gt;|name|&lt;/code&gt; instead of &lt;code&gt;%{name}&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"Easy"&lt;/em&gt;, you might think. &lt;em&gt;"Just change the regex!&lt;/em&gt;". And you would be right. That's what Polyglot does. It uses a custom regex called &lt;code&gt;tokenRegex&lt;/code&gt; that is built when you create an instance of Polyglot:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Polyglot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;opts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tokenRegex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;constructTokenRegex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;interpolation&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This &lt;code&gt;tokenRegex&lt;/code&gt; is then passed to &lt;code&gt;transformPhrase&lt;/code&gt; when you call &lt;code&gt;t&lt;/code&gt; on a key. It is assigned to &lt;code&gt;interpolationRegex&lt;/code&gt; if it holds a value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;transformPhrase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;phrase&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;substitutions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;locale&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;tokenRegex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;interpolationRegex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;tokenRegex&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;defaultTokenRegex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;constructTokenRegex&lt;/code&gt; is a fairly simple function. Its purpose is to return a new regex based on the given prefix and suffix:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;delimiter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;||||&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// ...&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;escape&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;[&lt;/span&gt;&lt;span class="sr"&gt;.*+?^${}()|[&lt;/span&gt;&lt;span class="se"&gt;\]\\]&lt;/span&gt;&lt;span class="sr"&gt;/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;$&amp;amp;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;constructTokenRegex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;prefix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;opts&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prefix&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;%{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;suffix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;opts&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;suffix&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;}&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;prefix&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;delimiter&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;suffix&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;delimiter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;RangeError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;"&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;delimiter&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;" token is reserved for pluralization&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;RegExp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;escape&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;prefix&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;(.*?)&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;escape&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;suffix&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;g&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are two things to consider, though:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It's not possible to choose a prefix or a suffix that is equal to &lt;code&gt;||||&lt;/code&gt; as it's used for pluralization.&lt;/li&gt;
&lt;li&gt;We &lt;strong&gt;must escape&lt;/strong&gt; the prefix and the suffix. But why is that? Well, you'll probably use special characters such as &lt;code&gt;{&lt;/code&gt;, or &lt;code&gt;[&lt;/code&gt; or maybe &lt;code&gt;*&lt;/code&gt;. However, these symbols are special regex characters, so we need to escape them with a backslash. That's the responsibility of the &lt;code&gt;escape&lt;/code&gt; function. It will replace the regex symbol with a backslash followed by the matched symbol (corresponds to &lt;code&gt;$&amp;amp;&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As an example, &lt;code&gt;constructTokenRegex({ prefix: '[[', suffix: ']]' })&lt;/code&gt; returns &lt;code&gt;/\[\[(.*?)\]\]/g&lt;/code&gt; (and not &lt;code&gt;/[[(.*?)]]/g&lt;/code&gt; ⚠️).&lt;/p&gt;

&lt;h2&gt;
  
  
  Smart count and plural groups
&lt;/h2&gt;

&lt;p&gt;Now the second part of &lt;code&gt;transformPhrase&lt;/code&gt;: pluralization. That one can be tough to build. Indeed, you have to make it possible for Polyglot to choose a phrase among others both based on a number and a locale. But a language can be radically different from another, plural forms included. For example, did you know that there are no plural forms in Chinese, but there are six in Arabic? Or that in French, zero is singular while it's plural in English? To make pluralization happen, we need to take account of all these rules.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: If you're interested, here are the other &lt;a href="http://www.unicode.org/cldr/charts/33/supplemental/language_plural_rules.html" rel="noopener noreferrer"&gt;plural rules&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Roughly speaking, here's what Polyglot does:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Reference all possible rules and map them to the corresponding locales.&lt;/li&gt;
&lt;li&gt;When you translate a phrase that need to be pluralized (with the &lt;code&gt;smart_count&lt;/code&gt; option), split it in multiple phrases based on a delimiter. Thus, you get an array of phrases (more precisely, all the plural forms of the phrase).&lt;/li&gt;
&lt;li&gt;Retrieve the rule associated with the locale given to Polyglot. This rule takes a number as a parameter and returns another number indicating which plural form to choose.&lt;/li&gt;
&lt;li&gt;Returns the correct phrase using the number returned by the rule (which acts as an &lt;strong&gt;array index&lt;/strong&gt;).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We are going to detail this step by step.&lt;/p&gt;

&lt;p&gt;First, here is an extract of all the rules and their corresponding locales:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;russianPluralGroups&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;lastTwo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;end&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;lastTwo&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lastTwo&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="mi"&gt;11&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;end&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="nx"&gt;end&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;end&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lastTwo&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;lastTwo&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;pluralTypes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;arabic&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// http://www.arabeyes.org/Plural_Forms&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;lastTwo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lastTwo&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;lastTwo&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;lastTwo&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;11&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;bosnian_serbian&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;russianPluralGroups&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;chinese&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;croatian&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;russianPluralGroups&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;french&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;german&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;pluralTypeToLanguages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;arabic&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ar&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;bosnian_serbian&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bs-Latn-BA&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bs-Cyrl-BA&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;srl-RS&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sr-RS&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;chinese&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id-ID&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ja&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ko&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ko-KR&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lo&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ms&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;th&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;th-TH&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;zh&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;croatian&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hr&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hr-HR&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;german&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fa&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;da&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;de&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;en&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;es&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fi&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;el&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;he&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hi-IN&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hu&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hu-HU&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;it&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;nl&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;no&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pt&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sv&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tr&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;french&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fr&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tl&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pt-br&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can see, for example, that for a german rule (which includes English), we return the plural form if the number is different than one, otherwise, we return the singular form.&lt;/p&gt;

&lt;p&gt;Now we can focus on the pluralization part of &lt;code&gt;transformPhrase&lt;/code&gt;. Here we will take account of the &lt;code&gt;locale&lt;/code&gt; parameter. The &lt;code&gt;currentLocale&lt;/code&gt; value of Polyglot is passed to &lt;code&gt;transformPhrase&lt;/code&gt; when calling &lt;code&gt;t&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;phrase&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;transformPhrase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;phrase&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;currentLocale&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tokenRegex&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To make pluralization happen, you need to add a &lt;code&gt;smart_count&lt;/code&gt; in your options (&lt;code&gt;substitutions&lt;/code&gt; object). Note that you can also pass a number instead of an options object. Polyglot will take that shortcut and transform it back to an options object with a &lt;code&gt;smart_count&lt;/code&gt; property.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;trim&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string.prototype.trim&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// ...&lt;/span&gt;

&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;split&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;split&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// ...&lt;/span&gt;

&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;delimiter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;||||&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// ...&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;transformPhrase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;phrase&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;substitutions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;locale&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;tokenRegex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;substitutions&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;phrase&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;phrase&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;substitutions&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;number&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;smart_count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;substitutions&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;substitutions&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;smart_count&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;texts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;split&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;delimiter&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nx"&gt;texts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;pluralTypeIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;locale&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;en&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;smart_count&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;texts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Interpolation code...&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step two&lt;/strong&gt;. If we do have a &lt;code&gt;smart_count&lt;/code&gt; option, we split the phrase into multiple parts thanks to the delimiter (&lt;code&gt;||||&lt;/code&gt;). As we are caching &lt;code&gt;split&lt;/code&gt;, we need to invoke the &lt;code&gt;result&lt;/code&gt; function thanks to the &lt;code&gt;call&lt;/code&gt; method. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;phrase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;I have one thing |||| I have many things&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;phrases&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;||||&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// ['I have one thing ', ' I have many things']&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, &lt;strong&gt;step 3&lt;/strong&gt;. We need to retrieve the rule associated with our locale. This happens thanks to the &lt;code&gt;pluralTypeIndex&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;Basically, &lt;code&gt;pluralTypeIndex&lt;/code&gt; takes a locale and a count. It invokes one of the functions defined in &lt;code&gt;pluralTypes&lt;/code&gt; with &lt;code&gt;count&lt;/code&gt; as a parameter. It can be &lt;code&gt;arabic(3)&lt;/code&gt;, for example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;pluralTypeIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;locale&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;pluralTypes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;pluralTypeName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;locale&lt;/span&gt;&lt;span class="p"&gt;)](&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nevertheless, we need to know beforehand which language rules our locale refers to. That's what &lt;code&gt;pluralTypeName&lt;/code&gt; does.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;langToTypeMap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mapping&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
  &lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mapping&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;langs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;langs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lang&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;lang&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;pluralTypeName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;locale&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;langToPluralType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;langToTypeMap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pluralTypeToLanguages&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;langToPluralType&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;locale&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
    &lt;span class="nx"&gt;langToPluralType&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;split&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;locale&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sr"&gt;/-/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
    &lt;span class="nx"&gt;langToPluralType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;en&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After building the map that associates a locale to the correct plural rule, we lookup in this map for the value of the given locale.&lt;/p&gt;

&lt;p&gt;You have to deal with one edge case here. Indeed, the locale can sometimes be composed and missing in the corresponding map. In that case, we first try to return the rule associated with the first part of the locale. Otherwise, we return the one associated to &lt;code&gt;en&lt;/code&gt; (&lt;code&gt;german&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;If you struggle to see what the &lt;code&gt;langToPluralType&lt;/code&gt; map looks like, here is an extract:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;ar&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;arabic&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bs-Latn-BA&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bosnian_serbian&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bs-Cyrl-BA&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bosnian_serbian&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;srl-RS&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bosnian_serbian&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sr-RS&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bosnian_serbian&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;chinese&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;id-ID&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;chinese&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;th-TH&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;chinese&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;zh&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;chinese&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;hr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;croatian&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hr-HR&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;croatian&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;fa&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;german&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;da&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;german&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;de&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;german&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;en&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;german&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's say we have &lt;code&gt;fa&lt;/code&gt; as a locale. Invoking &lt;code&gt;pluralTypeName&lt;/code&gt; will lookup in the map above if &lt;code&gt;fa&lt;/code&gt; is mapped to a value. It turns out it is, so it will return &lt;code&gt;german&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;However, in the case of &lt;code&gt;en-US&lt;/code&gt;, it doesn't correspond to anything in the map, so it will split this locale based on &lt;code&gt;-&lt;/code&gt;, and will retrieve the first part of it: &lt;code&gt;en&lt;/code&gt;. Thus, we have a locale to look for in the map.&lt;/p&gt;

&lt;p&gt;Finally, in &lt;code&gt;pluralTypeIndex&lt;/code&gt;, we can invoke the correct language rule to the function with the count. The result of that function will be trimed as there may be some whitespaces between the end (or beginning) of the phrase and &lt;code&gt;||||&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: We are thinking in terms of indexes. It implies that your phrases should be delimited in ascending order and that you should be exhaustive on the possible plural forms your phrase may take. Otherwise, Polyglot may just return the first phrase.&lt;/p&gt;

&lt;p&gt;Let's recap pluralization on an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;polyglot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Polyglot&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;polyglot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;thing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;There is %{smart_count} thing |||| There are %{smart_count} things&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;polyglot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;t&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;thing&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;smart_count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We haven't provided a &lt;code&gt;locale&lt;/code&gt; to polyglot, so it's &lt;code&gt;en&lt;/code&gt; by default.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Is there a &lt;code&gt;smart_count&lt;/code&gt; on the &lt;code&gt;options&lt;/code&gt; or is it a number? Yes, let's know which phrase to return.&lt;/li&gt;
&lt;li&gt;Split the phrase in multiple phrases: &lt;code&gt;['There is %{smart_count} thing ', ' There are %{smart_count} things']&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;After building the &lt;code&gt;langToPluralType&lt;/code&gt; map, we retrieve the plural rule associated to &lt;code&gt;en&lt;/code&gt;, that is to say &lt;code&gt;german&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Let's invoke the &lt;code&gt;german&lt;/code&gt; function with the correct count: &lt;code&gt;german(1)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;The german rule checks the following: &lt;code&gt;n !== 1 ? 1 : 0&lt;/code&gt;. Here, &lt;code&gt;1&lt;/code&gt; is not different from &lt;code&gt;1&lt;/code&gt;, then return &lt;code&gt;0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Select the first phrase (index &lt;code&gt;0&lt;/code&gt;) from the multiple phrases and trim it: &lt;code&gt;There is %{smart_count} thing&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Interpolation: replace &lt;code&gt;smart_count&lt;/code&gt; in the phrase: &lt;code&gt;There is 1 thing&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Another example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;polyglot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Polyglot&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;locale&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fr&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;polyglot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;thing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Il n'y a rien |||| Il y a plein de choses&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;polyglot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;t&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;thing&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here the &lt;code&gt;locale&lt;/code&gt; is &lt;code&gt;fr&lt;/code&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Is there a &lt;code&gt;smart_count&lt;/code&gt; on the &lt;code&gt;options&lt;/code&gt; or is it a number? Yes, let's know which phrase to return.&lt;/li&gt;
&lt;li&gt;Split the phrase in multiple phrases: &lt;code&gt;["Il n'y a rien ", " Il y a plein de choses"]&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;After building the &lt;code&gt;langToPluralType&lt;/code&gt; map, we retrieve the plural rule associated to &lt;code&gt;fr&lt;/code&gt;, that is to say &lt;code&gt;french&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Let's invoke the &lt;code&gt;french&lt;/code&gt; function with the correct count: &lt;code&gt;french(4)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;The french rule checks the following: &lt;code&gt;n &amp;gt; 1 ? 1 : 0&lt;/code&gt;. Here, &lt;code&gt;4&lt;/code&gt; is greater than &lt;code&gt;1&lt;/code&gt;, then return &lt;code&gt;1&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Select the second phrase (index &lt;code&gt;1&lt;/code&gt;) from the multiple phrases and trim it: &lt;code&gt;Il y a plein de choses&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Other features
&lt;/h2&gt;

&lt;p&gt;Are you still with me? Great. The next methods are pretty easy to understand. They act more as utilities instead as a feature on their own.&lt;/p&gt;

&lt;h3&gt;
  
  
  Unset
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;unset&lt;/code&gt; is quite similar to &lt;code&gt;extend&lt;/code&gt; code-wise. It takes a parameter that can either be a string or an object. If it's a string, delete the key from the internal &lt;code&gt;phrases&lt;/code&gt; object. If it's an object, iterate over the keys of the object passed and remove them if the associated value if it's not an object. Otherwise, apply the unset function on the associated object value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;Polyglot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;unset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;morePhrases&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;prefix&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;morePhrases&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;delete&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;phrases&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;morePhrases&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nx"&gt;morePhrases&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;phrase&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;prefixedKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;prefix&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;prefix&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;phrase&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;object&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;unset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;phrase&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;prefixedKey&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="k"&gt;delete&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;phrases&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;prefixedKey&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Clear
&lt;/h3&gt;

&lt;p&gt;As you have an internal &lt;code&gt;phrases&lt;/code&gt; object that contains all your keys and phrases, &lt;code&gt;clear&lt;/code&gt; is fairly simple. Just empty the object:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;Polyglot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clear&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;phrases&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Replace
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;replace&lt;/code&gt; allows you to replace your current set of phrases by another one. So you just need to &lt;strong&gt;clear&lt;/strong&gt; the current &lt;code&gt;phrases&lt;/code&gt; and &lt;strong&gt;extend&lt;/strong&gt; it with the other set:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;Polyglot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;replace&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newPhrases&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;clear&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newPhrases&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Has
&lt;/h3&gt;

&lt;p&gt;As we already require an &lt;code&gt;has&lt;/code&gt; package that checks for a key in an object, we just have to apply the &lt;code&gt;has&lt;/code&gt; function on the internal &lt;code&gt;phrases&lt;/code&gt; with a given key:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;Polyglot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;has&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;has&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;phrases&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Locale
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;locale&lt;/code&gt; method has two behaviors:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If a new locale is provided, set the internal &lt;code&gt;currentLocale&lt;/code&gt; to it.&lt;/li&gt;
&lt;li&gt;Otherwise, return the current locale.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;Polyglot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;locale&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newLocale&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newLocale&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;currentLocale&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;newLocale&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;currentLocale&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What I've learned
&lt;/h2&gt;

&lt;p&gt;We're done with the code! Reverse-engineering a library is a great way to upgrade your skills. By diving into the code source of Polyglot, I had the opportunity to enhance my knowledge of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How to handle the internationalization in an application&lt;/li&gt;
&lt;li&gt;Prototypes, the prototype chain, and closures&lt;/li&gt;
&lt;li&gt;Regular expressions and their use in &lt;code&gt;String.prototype.replace&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Using &lt;code&gt;call&lt;/code&gt; to apply a function to another object&lt;/li&gt;
&lt;li&gt;The plural rules specific to each language&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I'm convinced that the most effective way to learn is by learning from real-world examples and practicing. The theory is great to a certain extent. I highly encourage you to do more reverse-engineering, and I hope that this article gave you the will to do so.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How the Github CLI Saves Me Time Every Day</title>
      <dc:creator>Thomas Lombart</dc:creator>
      <pubDate>Thu, 08 Oct 2020 12:03:35 +0000</pubDate>
      <link>https://dev.to/thomaslombart/how-to-save-time-with-github-cli-b9n</link>
      <guid>https://dev.to/thomaslombart/how-to-save-time-with-github-cli-b9n</guid>
      <description>&lt;p&gt;What if I told you it's possible to manage your GitHub repository within the CLI? No more pointing and clicking on a user interface, just commands. That would mean faster work with less context-switching, right? Brace yourself. GitHub's official command line is right here for you.&lt;/p&gt;

&lt;p&gt;Triaging issues, creating or checking out pull requests, releasing packages, forking repos, even creating gists can now be done from your terminal. And we all know its power and how fast it can be. Using GitHub CLI has been a real win for my workflow. Want to learn more? It all happens down here. 👇&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting started
&lt;/h2&gt;

&lt;p&gt;First things first, installing GitHub CLI. If you're a macOS user, run &lt;code&gt;brew install gh&lt;/code&gt;. If you're a Windows user, you can install it via &lt;a href="https://vuejs.org/" rel="noopener noreferrer"&gt;scoop&lt;/a&gt; or &lt;a href="https://chocolatey.org/" rel="noopener noreferrer"&gt;Chocolatey&lt;/a&gt;. As for Linux, you have great installation instructions here: &lt;a href="https://github.com/cli/cli/blob/trunk/docs/install_linux.md" rel="noopener noreferrer"&gt;Installing gh on Linux&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It's installed? Good. As said previously, GitHub CLI aims at managing your workflow directly from the terminal. But it needs to have access to your account for that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gh auth login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You'll be prompted to configure your preferred Git protocol, pick whatever suits you here. If you choose SSH, make sure you &lt;a href="https://docs.github.com/en/free-pro-team@latest/github/authenticating-to-github/connecting-to-github-with-ssh" rel="noopener noreferrer"&gt;added a SSH key to your account&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Finally, set your preferred editor. In my case, I mostly work with VS Code. Thus, I ran:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gh config &lt;span class="nb"&gt;set &lt;/span&gt;editor &lt;span class="s2"&gt;"code --wait"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note: The &lt;code&gt;--wait&lt;/code&gt; option is essential here. Indeed, when you are prompted to enter a longer message (such as a pull request's body), the CLI needs to have a signal you're done, such as closing a VS Code window.&lt;/p&gt;

&lt;p&gt;You're now good to go.&lt;/p&gt;

&lt;h2&gt;
  
  
  Commands
&lt;/h2&gt;

&lt;p&gt;What can GitHub CLI do for you? Good question. As with most CLIs, you have a dedicated help command for that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;➜ gh &lt;span class="nb"&gt;help
&lt;/span&gt;Work seamlessly with GitHub from the &lt;span class="nb"&gt;command &lt;/span&gt;line.

USAGE
  gh &amp;lt;&lt;span class="nb"&gt;command&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &amp;lt;subcommand&amp;gt; &lt;span class="o"&gt;[&lt;/span&gt;flags]

CORE COMMANDS
  gist:       Create gists
  issue:      Manage issues
  &lt;span class="nb"&gt;pr&lt;/span&gt;:         Manage pull requests
  release:    Manage GitHub releases
  repo:       Create, clone, fork, and view repositories

ADDITIONAL COMMANDS
  &lt;span class="nb"&gt;alias&lt;/span&gt;:      Create &lt;span class="nb"&gt;command &lt;/span&gt;shortcuts
  api:        Make an authenticated GitHub API request
  auth:       Login, &lt;span class="nb"&gt;logout&lt;/span&gt;, and refresh your authentication
  completion: Generate shell completion scripts
  config:     Manage configuration &lt;span class="k"&gt;for &lt;/span&gt;gh
  &lt;span class="nb"&gt;help&lt;/span&gt;:       Help about any &lt;span class="nb"&gt;command

&lt;/span&gt;FLAGS
  &lt;span class="nt"&gt;--help&lt;/span&gt;      Show &lt;span class="nb"&gt;help &lt;/span&gt;&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="nb"&gt;command&lt;/span&gt;
  &lt;span class="nt"&gt;--version&lt;/span&gt;   Show gh version

EXAMPLES
  &lt;span class="nv"&gt;$ &lt;/span&gt;gh issue create
  &lt;span class="nv"&gt;$ &lt;/span&gt;gh repo clone cli/cli
  &lt;span class="nv"&gt;$ &lt;/span&gt;gh &lt;span class="nb"&gt;pr &lt;/span&gt;checkout 321

...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's quite helpful. Most of the time, you'll use core commands. Use the &lt;code&gt;--help&lt;/code&gt; option to know what you can do with each of them. Here's an example with the &lt;code&gt;issue&lt;/code&gt; command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;➜ gh issue &lt;span class="nt"&gt;--help&lt;/span&gt;
Work with GitHub issues

USAGE
  gh issue &amp;lt;&lt;span class="nb"&gt;command&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;flags]

CORE COMMANDS
  close:      Close issue
  create:     Create a new issue
  list:       List and filter issues &lt;span class="k"&gt;in &lt;/span&gt;this repository
  reopen:     Reopen issue
  status:     Show status of relevant issues
  view:       View an issue

FLAGS
  &lt;span class="nt"&gt;-R&lt;/span&gt;, &lt;span class="nt"&gt;--repo&lt;/span&gt; OWNER/REPO   Select another repository using the OWNER/REPO format

INHERITED FLAGS
  &lt;span class="nt"&gt;--help&lt;/span&gt;   Show &lt;span class="nb"&gt;help &lt;/span&gt;&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="nb"&gt;command

&lt;/span&gt;ARGUMENTS
  An issue can be supplied as argument &lt;span class="k"&gt;in &lt;/span&gt;any of the following formats:
  - by number, e.g. &lt;span class="s2"&gt;"123"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; or
  - by URL, e.g. &lt;span class="s2"&gt;"https://github.com/OWNER/REPO/issues/123"&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;

EXAMPLES
  &lt;span class="nv"&gt;$ &lt;/span&gt;gh issue list
  &lt;span class="nv"&gt;$ &lt;/span&gt;gh issue create &lt;span class="nt"&gt;--label&lt;/span&gt; bug
  &lt;span class="nv"&gt;$ &lt;/span&gt;gh issue view &lt;span class="nt"&gt;--web&lt;/span&gt;

...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, I don't want to explain to you each command. On the official GitHub CLI website, you can find a &lt;a href="https://cli.github.com/manual/" rel="noopener noreferrer"&gt;well-explained manual of all these commands&lt;/a&gt;. Instead, I'm going to show you examples of how this CLI can improve your workflow in your everyday developer's life.&lt;/p&gt;

&lt;h2&gt;
  
  
  Examples
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Create a PR
&lt;/h3&gt;

&lt;p&gt;Let's say you work on a brand new feature for your company or open-source project. You finished the work and want to create a PR on GitHub. Usually, you would have gone to &lt;a href="https://github.com" rel="noopener noreferrer"&gt;github.com&lt;/a&gt; to open the PR, right? Well, now, you can do exactly the same with &lt;code&gt;gh pr create&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;➜ gh &lt;span class="nb"&gt;pr &lt;/span&gt;create
? Where should we push the &lt;span class="s1"&gt;'feat/signup'&lt;/span&gt; branch? company/repo

Creating pull request &lt;span class="k"&gt;for &lt;/span&gt;feat/signup into master &lt;span class="k"&gt;in &lt;/span&gt;company/repo

? Title feat&lt;span class="o"&gt;(&lt;/span&gt;signup&lt;span class="o"&gt;)&lt;/span&gt;: Add signup screen
? Body &amp;lt;Received&amp;gt;
? What&lt;span class="s1"&gt;'s next?  [Use arrows to move, type to filter]
&amp;gt; Submit
  Continue in browser
  Add metadata
  Cancel
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, this command is interactive. I provided the title, the body in VS Code, and then submitted the PR in a snap.&lt;/p&gt;

&lt;p&gt;Suppose you were to provide some metadata such as the reviewers, assignees, or labels. In that case, you could also do it by selecting &lt;code&gt;Add metadata&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;? What's next? Add metadata
? What would you like to add?  [Use arrows to move, space to select, &amp;lt;right&amp;gt; to all, &amp;lt;left&amp;gt; to none, type to filter]
  [ ]  Reviewers
&amp;gt; [x]  Assignees
  [ ]  Labels
  [ ]  Projects
  [ ]  Milestone
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  See relevant pull requests
&lt;/h3&gt;

&lt;p&gt;It's common for a developer to have many tasks at once: your review is requested on a piece of code, you fix a bug while waiting for a review on one of your feature PRs. In that case, you may want to know the statuses to know your next actions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; gh &lt;span class="nb"&gt;pr &lt;/span&gt;status

Relevant pull requests &lt;span class="k"&gt;in &lt;/span&gt;company/repo

Current branch
  &lt;span class="c"&gt;#234  fix(homepage): Avatar is not shown if account created with Google [fix/avatar]&lt;/span&gt;
  - Checks pending - Review required

Created by you
  &lt;span class="c"&gt;#234  fix(homepage): Avatar is not shown if account created with Google [fix/avatar]&lt;/span&gt;
  - Checks pending - Review required
  &lt;span class="c"&gt;#224  feat(signup): Add signup screen [feat/signup]&lt;/span&gt;
  ✓ Checks passing - Review required

Requesting a code review from you
  &lt;span class="c"&gt;#231  docs(onboarding): Add docs on how to deploy on production [docs/onboarding]&lt;/span&gt;
  ✓ Checks passing
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;How convenient this command is. I know at a glance what's going on with your PRs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Current branch&lt;/strong&gt;: I'm working on a fix&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Created by you&lt;/strong&gt;: My fix has some checks pending, and I didn't get any reviews yet. I also have another opened PR that passes the checks, but I haven't received any reviews.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Requesting a code review from you&lt;/strong&gt;: A PR on documentation has passed the checks and I need to give my review.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If I were to review the docs PR, I could simply type &lt;code&gt;gh pr view 231&lt;/code&gt;, and view the PR on the terminal or on the web using the &lt;code&gt;--web&lt;/code&gt; option.&lt;/p&gt;

&lt;h3&gt;
  
  
  Waiting for Travis
&lt;/h3&gt;

&lt;p&gt;Let's say your PR is already opened and you got some review comments. You worked through your comments, pushed your code, and wanted to know if you can merge the PR. Maybe you've set up Travis CI, and you're waiting for the build to pass:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; gh &lt;span class="nb"&gt;pr &lt;/span&gt;checks

➜ gh &lt;span class="nb"&gt;pr &lt;/span&gt;checks
All checks were successful
0 failing, 1 successful, and 0 pending checks

✓  Travis CI - Pull Request  5m26s  https://travis-ci.com/github/comp...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(Let's be honest, one of our favorite tasks, as developers, is to wait for Travis, isn't it? 😄)&lt;/p&gt;

&lt;p&gt;If everything's OK, you can also merge the PR right from your terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gh &lt;span class="nb"&gt;pr &lt;/span&gt;merge
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Testing a colleague's changes
&lt;/h3&gt;

&lt;p&gt;Developers, when reviewing code, tend to focus on the code only. It's indeed faster, but perhaps it's worth it to check out the changes live. It allows you to have a better vision of what the code really implies and its value.&lt;/p&gt;

&lt;p&gt;Now, you can check out your colleague's branch with GitHub CLI. Use the &lt;code&gt;pr checkout&lt;/code&gt; along with the pull request's number, and you're good to go:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gh &lt;span class="nb"&gt;pr &lt;/span&gt;checkout 6838
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As a front-end developer, I often use it to make sure the UI changes properly work.&lt;/p&gt;

&lt;p&gt;Note that you can find an example of this command on GitHub directly:&lt;/p&gt;

&lt;p&gt;
  src="/save-time-github-cli/github-open.png"&lt;br&gt;
  alt="A screenshot of GitHub's button open with"&lt;br&gt;
/&amp;gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Your next issue
&lt;/h3&gt;

&lt;p&gt;You're maintaining an open-source project, and you want to know what's the next thing you can work on. Then, you can browse your issues with the &lt;code&gt;issue&lt;/code&gt; command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; gh issue list

Showing 15 of 15 open issues in testing-library/eslint-plugin-testing-library

#227  [await-async-utils] false p...  (bug)                           about 23 days ago
#222  [await-async-query] Support...  (help wanted)                   about 1 month ago
#219  feature request: no-await-f...                                  about 1 month ago
#202  Support eslint fix command ...  (enhancement)                   about 2 months ago
#198  Move custom render function...  (BREAKING CHANGE)               about 18 days ago
#187  Autogenerate configs from r...                                  about 3 months ago
:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Maybe you don't have much time and you want to fix a bug. Then, filter them with the &lt;code&gt;--label&lt;/code&gt; option:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; gh issue list &lt;span class="nt"&gt;--label&lt;/span&gt; bug

Showing 2 of 2 issues &lt;span class="k"&gt;in &lt;/span&gt;testing-library/eslint-plugin-testing-library that match your search

&lt;span class="c"&gt;#227  [await-async-utils] false positive pr...  (bug)  about 23 days ago&lt;/span&gt;
&lt;span class="c"&gt;#141  Lint RenderResult when returned from ...  (bug)  about 2 months ago&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are lot of other filtering options. Don't hesitate to run &lt;code&gt;gh issue list --help&lt;/code&gt; to know more.&lt;/p&gt;

&lt;h3&gt;
  
  
  Quick approval
&lt;/h3&gt;

&lt;p&gt;Someone at your company spotted a bug in production and needs to quickly ship a small fix. Let's say its PR is the number #211. You can approve it in just two commands:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Visualize the changes: &lt;code&gt;gh pr diff 211&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Approve the PR &lt;code&gt;gh pr review 211 --approve&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Your colleague gets a fast approval and you don't fully interrupt your workflow. I call that a win-win.&lt;/p&gt;

&lt;h3&gt;
  
  
  Contributing to an open-source project
&lt;/h3&gt;

&lt;p&gt;At the time of writing, it's the 2020 edition of Hacktoberfest. Maybe you want to make a contribution to open-source. Usually, that includes forking a repo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;➜ gh repo fork organization/repo
- Forking organization/repo...
✓ Created fork user/organization/repo
? Would you like to clone the fork? Yes
Cloning into &lt;span class="s1"&gt;'repo'&lt;/span&gt;...
...
✓ Cloned fork
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Some maintainers label issues as &lt;code&gt;good first issue&lt;/code&gt; for the newcomers. Then, you can search through them from the CLI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gh issue list &lt;span class="nt"&gt;--label&lt;/span&gt; &lt;span class="s2"&gt;"good first issue"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note: if you're considering contributing to a project? Please &lt;strong&gt;don't spam them&lt;/strong&gt; with meaningless contributions such as adding "Amazing project" next to a title or similar. Open source maintainers are working hard on their beloved repos. ❤️&lt;/p&gt;

&lt;h2&gt;
  
  
  Using both GitHub and GitHub CLI
&lt;/h2&gt;

&lt;p&gt;As you can see, GitHub CLI is powerful and can improve your workflow. It has already become a tool I'm using every day. Approving a pull request, finding an issue on which I can work, quickly see if a build pass, it's a real time-saver, and it has become a tool I'm using every day.&lt;/p&gt;

&lt;p&gt;It doesn't mean you should use only GitHub CLI as of now. Don't forget the UI. For example, I still find it useful to do a complete review or browsing issues. Use what suits your needs best.&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>github</category>
      <category>tooling</category>
    </item>
    <item>
      <title>How to Become a Front-End Developer</title>
      <dc:creator>Thomas Lombart</dc:creator>
      <pubDate>Mon, 28 Sep 2020 06:10:19 +0000</pubDate>
      <link>https://dev.to/thomaslombart/how-to-become-a-front-end-developer-4ema</link>
      <guid>https://dev.to/thomaslombart/how-to-become-a-front-end-developer-4ema</guid>
      <description>&lt;p&gt;A few years ago, I became a software engineer, and I took the front-end path. Don't get me wrong, front-end development is not just HTML and CSS, far from it! You also have to know JavaScript, Git, performance, accessibility, design, and much more. Building an excellent front-end application is a &lt;strong&gt;challenging&lt;/strong&gt; task.&lt;/p&gt;

&lt;p&gt;The path to getting a job as a front-end developer is not an easy one. But you're lucky. I've been there, and I know what works and what doesn't to get hired! There are four main steps in this journey:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Getting the knowledge&lt;/li&gt;
&lt;li&gt;Building projects&lt;/li&gt;
&lt;li&gt;Searching for a job&lt;/li&gt;
&lt;li&gt;Succeeding the interview&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;My goal with this post is to clarify how you can become a front-end developer and a &lt;em&gt;good one&lt;/em&gt;. Without further ado, let's start with the knowledge and the resources to achieve this goal!&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting the knowledge
&lt;/h2&gt;

&lt;p&gt;Nowadays, front-end development is overwhelming. There's so much to learn! Maybe you think that you'll never get there. Trust me. &lt;strong&gt;You won't know it all.&lt;/strong&gt; The good news is that you have to focus on learning the right things. However, &lt;strong&gt;you'll need to practice.&lt;/strong&gt; Be active in your learning journey; it's the key to mastery!&lt;/p&gt;

&lt;p&gt;You'll find below the required knowledge of front-end developers to have a successful career. I added some resources, how you could put your skills to practice, and the blog posts I wrote on this (because why not self-promoting? 😏)&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: there's no partnership with the resources I included. I just found them well made.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  HTML and CSS
&lt;/h3&gt;

&lt;p&gt;HTML represents the structure of a web page, and CSS its layout. You'll use these two technologies every day, so you need to get comfortable with this!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Resources: You can check out &lt;a href="https://www.freecodecamp.org/learn" rel="noopener noreferrer"&gt;freeCodeCamp&lt;/a&gt;, especially the basic HTML and basic CSS sections.&lt;/li&gt;
&lt;li&gt;Practice: build a simple page. Maybe a landing page or a cooking recipe.&lt;/li&gt;
&lt;li&gt;Blog posts: &lt;a href="https://thomaslombart.com/writing-blazing-fast-HTML-code/" rel="noopener noreferrer"&gt;Writing Blazing Fast HTML Code&lt;/a&gt;, &lt;a href="https://thomaslombart.com/how-to-get-better-at-writing-css/" rel="noopener noreferrer"&gt;How to Get Better at Writing CSS&lt;/a&gt; and &lt;a href="https://thomaslombart.com/how-to-make-a-list-responsive/" rel="noopener noreferrer"&gt;How to Make a Responsive Grid With Only Three Lines of CSS&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  JavaScript
&lt;/h3&gt;

&lt;p&gt;That's what powers up your apps. It's a programming language that is important to any web app. JavaScript is being used everywhere: for the servers, for desktop applications, or even for mobile apps! It's an essential skill for a front-end developer.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Resources: You can continue with freeCodeCamp on this one, or you can also check out a course from Wes Bos: &lt;a href="https://beginnerjavascript.com/" rel="noopener noreferrer"&gt;Beginner JavaScript&lt;/a&gt;. If you're practice-oriented, I highly recommend &lt;a href="https://javascript30.com/" rel="noopener noreferrer"&gt;JavaScript 30&lt;/a&gt; from Wes Bos as well.&lt;/li&gt;
&lt;li&gt;Practice: You should be able to build a first small app, such as a to-do app or a countdown.&lt;/li&gt;
&lt;li&gt;Blog posts: &lt;a href="https://thomaslombart.com/what-you-should-know-about-js-arrays/" rel="noopener noreferrer"&gt;What You Should Know About JavaScript Arrays&lt;/a&gt; and &lt;a href="https://thomaslombart.com/object-array-destructuring-javascript/" rel="noopener noreferrer"&gt;Object and Array Destructuring in JavaScript&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  CSS Framework
&lt;/h3&gt;

&lt;p&gt;Pure CSS is good. But it's not always easy to write some. Try to learn a CSS framework like &lt;a href="https://tailwindcss.com/" rel="noopener noreferrer"&gt;TailwindCSS&lt;/a&gt;, &lt;a href="https://bulma.io/" rel="noopener noreferrer"&gt;Bulma&lt;/a&gt; or &lt;a href="https://getbootstrap.com/" rel="noopener noreferrer"&gt;Bootstrap&lt;/a&gt;. Such frameworks are often used in companies, and it's important to get familiar with them.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Resources: Tailwind CSS as a set of &lt;a href="https://tailwindcss.com/course/setting-up-tailwind-and-postcss" rel="noopener noreferrer"&gt;screencasts&lt;/a&gt; if you're interested. Generally just, reading the docs of the CSS frameworks is enough.&lt;/li&gt;
&lt;li&gt;Practice: improve the page you build while learning HTML and CSS or the app you created with JavaScript. It's your choice!&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Version control (Git &amp;amp; GitHub)
&lt;/h3&gt;

&lt;p&gt;Version control is useful for working together on the same project. You can't escape it, so get comfortable with &lt;code&gt;git commit,&lt;/code&gt; &lt;code&gt;git push,&lt;/code&gt; or branches. You also need to learn how to work with a source code management platform such as &lt;a href="https://github.com" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;, &lt;a href="https://about.gitlab.com" rel="noopener noreferrer"&gt;GitLab&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Resources: &lt;a href="https://guides.github.com" rel="noopener noreferrer"&gt;Guides from GitHub&lt;/a&gt; especially the &lt;a href="https://guides.github.com/activities/hello-world/" rel="noopener noreferrer"&gt;beginner one&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Practice: Create an account on GitHub. Add the previous projects you made (landing page, to-do app, or anything code-related you did). It'll make you practice the famous &lt;code&gt;git status&lt;/code&gt; &lt;code&gt;git add&lt;/code&gt;, &lt;code&gt;git commit&lt;/code&gt;, &lt;code&gt;git push&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  JS Framework
&lt;/h3&gt;

&lt;p&gt;Most companies don't work with pure JS. They use a &lt;strong&gt;framework&lt;/strong&gt; that allows them to be more productive and write great apps. There are three leading solutions on the market right now: React, Vue, and Angular (though it tends to be less used). &lt;strong&gt;React and Vue are the most popular&lt;/strong&gt;, so I strongly recommend learning one of them to optimize your chances of getting hired.&lt;/p&gt;

&lt;p&gt;By learning a JS framework, you'll learn package managers such as &lt;a href="https://www.npmjs.com" rel="noopener noreferrer"&gt;npm&lt;/a&gt; and &lt;a href="https://yarnpkg.com" rel="noopener noreferrer"&gt;yarn&lt;/a&gt;. You'll also learn some tooling and how to interact with APIs. Don't worry. The resources I included below cover all of this.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Resource: &lt;a href="https://tylermcginnis.com/courses/react/" rel="noopener noreferrer"&gt;An excellent React course from Tyler McGinnis&lt;/a&gt;. Once finished, you can also take the &lt;a href="https://tylermcginnis.com/courses/react-hooks/" rel="noopener noreferrer"&gt;React hooks one&lt;/a&gt; to learn the latest technologies. Alternatively, there's Andrei Neagoie, who created a complete course: &lt;a href="https://www.udemy.com/course/complete-react-developer-zero-to-mastery/" rel="noopener noreferrer"&gt;Complete React Developer&lt;/a&gt;. On the Vue side, you can rely on &lt;a href="https://www.vuemastery.com/courses-path/beginner" rel="noopener noreferrer"&gt;Vue Mastery&lt;/a&gt; or &lt;a href="https://vueschool.io/courses" rel="noopener noreferrer"&gt;Vue School&lt;/a&gt;, especially &lt;a href="https://vueschool.io/courses/the-vuejs-master-class" rel="noopener noreferrer"&gt;The Vue.js Master Class&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Practice: you can build a more advanced app here. Maybe a weather app, a movie search app, or if you want, you can make a second version of a to-do app.&lt;/li&gt;
&lt;li&gt;Blog posts: &lt;a href="https://thomaslombart.com/getting-started-with-vue/" rel="noopener noreferrer"&gt;Getting Started with Vue&lt;/a&gt; and &lt;a href="https://thomaslombart.com/how-to-create-an-app-with-vue/" rel="noopener noreferrer"&gt;How to Create an App with Vue CLI&lt;/a&gt;. Check them out to have a taste of Vue if you're learning React. I also wrote a post related to tooling for React: &lt;a href="https://thomaslombart.com/setup-eslint-prettier-react/" rel="noopener noreferrer"&gt;How to Setup ESLint and Prettier for Your React Apps&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Modern CSS
&lt;/h3&gt;

&lt;p&gt;CSS is back again! Now that you know how to build an app with a JS framework, you need to get advanced CSS skills: Flexbox, Grid, preprocessors, the whole thing! It may be interesting to look into CSS-in-JS solutions like &lt;a href="https://emotion.sh/docs/introduction" rel="noopener noreferrer"&gt;Emotion&lt;/a&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Resource: &lt;a href="https://www.udemy.com/course/advanced-css-and-sass/" rel="noopener noreferrer"&gt;Advanced CSS and Sass&lt;/a&gt; from Jonas Schmedtmann. You'll learn how to build well-designed pages on top of it!&lt;/li&gt;
&lt;li&gt;Practice: remember the landing page you built? Revamp it with your new shiny CSS skills. It may also be a good time to build the first version of your portfolio.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Trust me or not, but that's &lt;strong&gt;all you need to know to get hired as a junior front-end developer.&lt;/strong&gt; Most companies know that you can't know everything. They're also interested in your career path. They know you'll gain more and more knowledge as time goes by.&lt;/p&gt;

&lt;p&gt;However, the skills above are not sufficient to be in the top front-end developers. You'll find below other skills to get if you want to get more comfortable in front-end development. You'll inevitably encounter them in your career.&lt;/p&gt;

&lt;h3&gt;
  
  
  Advanced JavaScript
&lt;/h3&gt;

&lt;p&gt;If you're sick of JavaScript, I don't have good news for you. Indeed, you may know how to use JavaScript to build cool apps, but that's not all. You should also know &lt;strong&gt;how it works under the hood&lt;/strong&gt; and the advanced JavaScript mechanisms, such as the event loop, closures, asynchronous stuff, or the prototype chain.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Resources: You can go on Frontend Masters and watch a course from Will Sentance entitled &lt;a href="https://frontendmasters.com/courses/javascript-hard-parts-v2/" rel="noopener noreferrer"&gt;JavaScript: the hard parts&lt;/a&gt;. You can also check out a course from Tyler McGinnis: &lt;a href="https://tylermcginnis.com/courses/advanced-javascript/" rel="noopener noreferrer"&gt;Advanced JavaScript&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Blog posts: &lt;a href="https://thomaslombart.com/reverse-engineering-airbnb-internationalization-library/" rel="noopener noreferrer"&gt;Reverse-Engineering Airbnb's Internationalization Library&lt;/a&gt; and &lt;a href="https://thomaslombart.com/resources-advanced-javascript/" rel="noopener noreferrer"&gt;Over 20 Resources to Advance Your JavaScript Skills&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Practice: practicing advanced JS is a bit hard to do. It's more of a long-term thing. The more you'll code, the better you'll get. So just practice JS here!&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Testing
&lt;/h3&gt;

&lt;p&gt;When building apps, there's always a point when you're not confident when it comes to deploying it or adding a new feature. Knowing how to test your front-end apps is an excellent asset in your toolset. The &lt;a href="https://testing-library.com/" rel="noopener noreferrer"&gt;Testing Library&lt;/a&gt; ecosystem will be your best friend when it comes to testing.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Resources: Kent C. Dodds is the go-to guy when it comes to testing. He has built a great course called &lt;a href="https://testingjavascript.com" rel="noopener noreferrer"&gt;Testing JavaScript&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Practice: Test one of your apps. Start small. You don't need to write elaborated tests right off the box! The goal is to get comfortable with tests.&lt;/li&gt;
&lt;li&gt;Blog posts: &lt;a href="https://thomaslombart.com/how-to-test-javascript-with-jest/" rel="noopener noreferrer"&gt;How to Test JavaScript With Jest&lt;/a&gt;, &lt;a href="https://thomaslombart.com/test-react-testing-library/" rel="noopener noreferrer"&gt;The Complete Beginner's Guide to Testing React Apps&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Accessibility
&lt;/h3&gt;

&lt;p&gt;You need to know how to build apps with accessibility in mind. &lt;strong&gt;Developers often forget accessibility, but it shouldn't be the case&lt;/strong&gt;. Think of all your users, including those who may be blind, colorblind, or use a voice reader.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Resources: Another course from Frontend Masters by Marcy Sutton: &lt;a href="https://frontendmasters.com/courses/javascript-accessibility/" rel="noopener noreferrer"&gt;Accessibility in JavaScript applications&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Practice: make an accessibility audit in one of your previous apps. Spot the problems and replace them with accessible solutions.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Performance
&lt;/h3&gt;

&lt;p&gt;Our world moves fast. We want everything right now. That's the same for apps; users can't stand a slow app. On top of that, it's terrible for your business. Learn how you can build performant apps.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Resources: Yet another course from Frontend Masters by Steve Kinney: &lt;a href="https://frontendmasters.com/courses/web-performance/" rel="noopener noreferrer"&gt;Web Performance&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Blog posts: &lt;a href="https://thomaslombart.com/3-ways-boost-web-app-performance/" rel="noopener noreferrer"&gt;3 Easy Ways to Boost Your Web Application Performance&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  SEO
&lt;/h3&gt;

&lt;p&gt;Without search engines, you can't find anything on the internet. SEO is about optimizing your sites so that anyone can quickly discover your website with the right keywords.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Resources: &lt;a href="https://ahrefs.com/" rel="noopener noreferrer"&gt;Ahrefs&lt;/a&gt;, one of the reference tool for SEO, has some great guides such as the following: &lt;a href="https://ahrefs.com/blog/seo-basics/" rel="noopener noreferrer"&gt;SEO Basics: Beginner’s Guide to SEO Success&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Practice: if you already have a portfolio, improve its SEO.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  SSR
&lt;/h3&gt;

&lt;p&gt;As of today, there are two main ways of rendering an application: on the client or the server. React and Vue render on the client by default, but that's not good for SEO. Lots of companies are looking into apps that render on the server like &lt;a href="https://nextjs.org/" rel="noopener noreferrer"&gt;Next&lt;/a&gt; or &lt;a href="https://nuxtjs.org/" rel="noopener noreferrer"&gt;Nuxt&lt;/a&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Resources: Wes Bos created a great course that's both on React, Next.js, and GraphQL: &lt;a href="https://advancedreact.com" rel="noopener noreferrer"&gt;Advanced React&lt;/a&gt;. It'll make you build an online store app!&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  TypeScript
&lt;/h3&gt;

&lt;p&gt;TypeScript is JavaScript but with types. More and more developers, especially in medium to large companies, appreciate the additional safety layer that TypeScript provides. Knowing it is a solid point for getting hired!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Resources: Did I already mention Frontend Masters? There's a course from Mike North on it called &lt;a href="https://frontendmasters.com/courses/typescript-v2/" rel="noopener noreferrer"&gt;TypeScript 3 Fundamentals&lt;/a&gt;. If you want the quick option, you can check out: &lt;a href="https://www.typescriptlang.org/docs/handbook/typescript-in-5-minutes.html" rel="noopener noreferrer"&gt;TypeScript in 5 minutes&lt;/a&gt; from the official docs.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  UI/UX Design
&lt;/h3&gt;

&lt;p&gt;Usually, this is not your job. These skills are for designers mostly. Designers create mockups, and it's your task to make them fully interactive. However, It's worth it to know &lt;strong&gt;how to build a mockup and play with colors, shadows, spacing, or components.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;On top of that, start-ups can't always afford a designer. Thus, knowing how to design, even if it's not much, is a big +1 for them!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Resources: &lt;a href="https://refactoringui.com/book/" rel="noopener noreferrer"&gt;Refactoring UI&lt;/a&gt; is a great book on design. I've heard lately of &lt;a href="https://shiftnudge.com/" rel="noopener noreferrer"&gt;Shift Nudge&lt;/a&gt; for getting the best UI skills. It's pricey, but it's worth it, in my opinion.&lt;/li&gt;
&lt;li&gt;Practice: design is like any skill. The more you'll practice, the better you'll get, period. For that, you can tackle the &lt;a href="https://www.dailyui.co/" rel="noopener noreferrer"&gt;Daily UI challenge.&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Blog posts: &lt;a href="https://thomaslombart.com/how-to-suck-less-at-colors/" rel="noopener noreferrer"&gt;How to Suck Less at Colors as a Developer&lt;/a&gt; and &lt;a href="https://thomaslombart.com/why-learn-design-developer/" rel="noopener noreferrer"&gt;Why Learning Design Is Important for Front-End Developers&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Databases and servers
&lt;/h3&gt;

&lt;p&gt;Once again, this won't be your job. However, it's also up to you to integrate into your front-end app the data you get from the server. It may be worth it to know how you can build a basic API to understand better what a back-end developer does in his day-to-day job.&lt;/p&gt;

&lt;p&gt;Pheeeew! That's all for the skills. There are still skills to get like learning how to build PWAs, static site generators like &lt;a href="https://www.gatsbyjs.org/" rel="noopener noreferrer"&gt;Gatsby&lt;/a&gt;, &lt;a href="https://graphql.org/" rel="noopener noreferrer"&gt;GraphQL&lt;/a&gt; or &lt;a href="https://www.docker.com" rel="noopener noreferrer"&gt;Docker&lt;/a&gt; but that post would get too long 😅&lt;/p&gt;

&lt;h2&gt;
  
  
  Side projects
&lt;/h2&gt;

&lt;p&gt;You have the required knowledge and built some small apps or web pages, that's great! Now it's time to put your skills to practice and to create some projects.&lt;/p&gt;

&lt;p&gt;One crucial thing to remember here: &lt;strong&gt;one big project is better than a hundred small projects&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Indeed, when you apply for a company, they need to know if they can trust you and pay you for your work. Building a project from scratch, &lt;strong&gt;even if it's not perfect&lt;/strong&gt;, is a great way to show that. Making a hundred small projects won't reveal how far you can go. Sure, It shows that you are passionate, but not that you're skilled! That's a common mistake you shouldn't fall into.&lt;/p&gt;

&lt;h3&gt;
  
  
  Building an app
&lt;/h3&gt;

&lt;p&gt;Here are the steps to start with a side project:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Find an app/project idea. Read &lt;a href="https://thomaslombart.com/how-to-find-ideas/" rel="noopener noreferrer"&gt;this post if you need help with finding ideas&lt;/a&gt; (self-promotion, again 🙃).&lt;/li&gt;
&lt;li&gt;Build the project if it's feasible. Use the technologies and skills you learned (front-end framework, CSS skills, etc.) and put your code on GitHub. You may be asked by companies to show how you code, and GitHub is great for that.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Don't quit!&lt;/strong&gt; Yes, your project will reach a point when the codebase becomes ugly, but that's the same for everyone, even for large companies.&lt;/li&gt;
&lt;li&gt;Deploy the project. Make it available for everyone. &lt;a href="https://www.netlify.com" rel="noopener noreferrer"&gt;Netlify&lt;/a&gt; or &lt;a href="https://zeit.co" rel="noopener noreferrer"&gt;ZEIT Now&lt;/a&gt; will be your best friends for that.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Project ideas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A Twitter clone&lt;/li&gt;
&lt;li&gt;An app to manage the movies and series you watch&lt;/li&gt;
&lt;li&gt;A chat app&lt;/li&gt;
&lt;li&gt;A &lt;a href="https://www.youtube.com/watch?v=hT3j87FMR6M" rel="noopener noreferrer"&gt;Todoist clone&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Anything you think of?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you don't feel confident in your back-end skills, look into &lt;a href="https://firebase.google.com/" rel="noopener noreferrer"&gt;Firebase&lt;/a&gt;. It's a powerful tool that is relatively easy to use.&lt;/p&gt;

&lt;h3&gt;
  
  
  Technical blog
&lt;/h3&gt;

&lt;p&gt;It's also a great idea to start a blog and learn to write technical posts, &lt;strong&gt;even if you're not an expert in your field&lt;/strong&gt;. Having such a blog shows both your writing and technical skills. On top of that, you reinforce your learning!&lt;/p&gt;

&lt;p&gt;You can create a blog with &lt;a href="https://www.gatsbyjs.com/" rel="noopener noreferrer"&gt;Gatsby&lt;/a&gt;, in particular, with &lt;a href="https://github.com/gatsbyjs/gatsby-starter-blog" rel="noopener noreferrer"&gt;this blog starter&lt;/a&gt;. In terms of post ideas, it's up to you. The world is your oyster here. Pick a topic and write about it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Portfolio
&lt;/h3&gt;

&lt;p&gt;Finally, build a portfolio with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A description&lt;/li&gt;
&lt;li&gt;Your skills&lt;/li&gt;
&lt;li&gt;Your projects&lt;/li&gt;
&lt;li&gt;Your technical posts if you have some&lt;/li&gt;
&lt;li&gt;How we can contact you or a contact form&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Job search
&lt;/h2&gt;

&lt;p&gt;Let's recap:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ You have the knowledge&lt;/li&gt;
&lt;li&gt;✅ You built one or two big projects or even a blog&lt;/li&gt;
&lt;li&gt;✅ You have a portfolio&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now is the time to find a job. That's a tough one because many companies are all looking for developers with at least five years of experience. Here are some tips for you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If a company is looking for a developer with at least one or two years of professional experience, &lt;strong&gt;apply!&lt;/strong&gt; Some companies put these kinds of criteria to have an entry barrier. You may be a great fit, so &lt;strong&gt;apply&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;You don't have to match every skill the company is looking for. Really. If they list TypeScript and you don't know TypeScript, that's OK. You can still apply.&lt;/li&gt;
&lt;li&gt;If you need to craft a motivational letter, &lt;strong&gt;personalize it&lt;/strong&gt;. The more you craft it for the company, the more it will have an impact.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Attend meetups in your city or online.&lt;/strong&gt; That's where you'll get contacts and exchange with other developers, product managers, or designers. Companies usually sponsor meetups to hire more people.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For the job search itself, you may find opportunities on &lt;a href="https://www.linkedin.com" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;, so you'll have to create a profile on it and put your projects there!&lt;/p&gt;

&lt;h2&gt;
  
  
  Interview
&lt;/h2&gt;

&lt;p&gt;So you've been selected, and you have an interview? Awesome. But you don't know what to expect. You are not confident. Maybe you think that it's not possible, they will make a mistake by hiring you, you're an imposter. &lt;strong&gt;Don't think that way.&lt;/strong&gt; Lots of developers believe they are not ready for the job. That's not the case. You built projects, you know how the technologies work, and that's valuable. Sure, you don't know it all, but nobody does.&lt;/p&gt;

&lt;p&gt;I don't know what's the exact interview process for all companies. But I know how it usually goes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You &lt;strong&gt;apply&lt;/strong&gt; to a job or someone contacts you, usually someone from the Human Resources department.&lt;/li&gt;
&lt;li&gt;You have a &lt;strong&gt;phone call&lt;/strong&gt;, or you meet in person the HR. You talk about your previous experiences, who you are, what you're searching for, the company, etc.&lt;/li&gt;
&lt;li&gt;You have a &lt;strong&gt;technical test&lt;/strong&gt;, usually with a company's front-end developer, a tech lead, or the CTO. You'll have to answer technical questions. It's also possible that you have a take-home project to do and then give the company's source code. If that's the case, polish it!&lt;/li&gt;
&lt;li&gt;You &lt;strong&gt;meet the founders of the company&lt;/strong&gt; or persons leading the company. They usually want to know whom they hire, so you'll discuss the company, your motivations, etc. Depending on the company's size, it may not happen.&lt;/li&gt;
&lt;li&gt;If all goes well, you get an &lt;strong&gt;offer&lt;/strong&gt;! Don't necessarily take the company with the best offer. Salary is an essential part of the job, but your happiness, how you feel in the company, and your career path matters too!&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let me warn you: sometimes, the process can be quite long.&lt;/p&gt;

&lt;p&gt;Here are some advice for you to succeed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Be professional but stay relaxed.&lt;/strong&gt; You're not interviewing for a bank. The first time I went to an interview, I was surprised at how chill the persons were. So, no pressure (Don't be too chill though, find the sweet spot 😄)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Show you're motivated&lt;/strong&gt; by the project. Unfortunately, getting hired for a first job is hard because you don't have previous experiences. However, you can show how much you want the job and contribute to the company.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Adapt your speech&lt;/strong&gt; to the person you're speaking to. Don't get too much in technical details if you talk to someone whose job is related to business.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Don't underestimate soft skills.&lt;/strong&gt; The interviewer will try to see if you can fit for the job and whether he can work with you or not, especially the persons in tech! Show how great it would be to work with you: communicate, smile, and stay humble. If you need to know which soft skills to get, I wrote a post on the &lt;a href="https://thomaslombart.com/soft-skills-developers/" rel="noopener noreferrer"&gt;soft skills every developer should have&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Don't lie during interviews.&lt;/strong&gt; If you don't know something, then you don't know. It's no big deal if you can't answer all the questions. Experienced developers don't like bull-shit developers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Developers always make trade-offs.&lt;/strong&gt; There's rarely a one-size-fits-all solution. Show that you are aware of that and think about &lt;strong&gt;what brings value to the company&lt;/strong&gt;. It demonstrates that you have deep thoughts, and it's much appreciated.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;OK, that was a long one. As said previously, becoming a developer is a long but rewarding path! I hope it gave you some insights into how you get a job.&lt;/p&gt;

</description>
      <category>career</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
    <item>
      <title>How to Build an Accessible Toggle Switch with Vue 3</title>
      <dc:creator>Thomas Lombart</dc:creator>
      <pubDate>Wed, 26 Aug 2020 10:15:13 +0000</pubDate>
      <link>https://dev.to/thomaslombart/how-to-build-a-reusable-and-accessible-toggle-switch-with-vue-3hh7</link>
      <guid>https://dev.to/thomaslombart/how-to-build-a-reusable-and-accessible-toggle-switch-with-vue-3hh7</guid>
      <description>&lt;p&gt;There are a lot of different UI components you can find on an app. The ones you'll find the most will probably be buttons, inputs, forms, or images. They are so common that HTML even provides default elements for them! However, it's not rare to encounter lesser-known components that you have to build by yourself.&lt;/p&gt;

&lt;p&gt;I worked lately on a switch/toggle component lately, something that looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8kol5mq5gsu7xpo4sv4i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8kol5mq5gsu7xpo4sv4i.png" alt="A screenshot of a toggle switch" width="566" height="218"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At first, it seems like a simple UI component. But building it can be tricky when you need to consider all the different states, its accessibility, and its reusability.&lt;/p&gt;

&lt;p&gt;Well, lucky you! Today I'm going to share with you how you can do the same.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: though I'm building it with Vue, the concepts can easily be applied to another framework such as React. Also, I'm using Vue 3 but don't be scared. There are not many differences with Vue 2 here!&lt;/em&gt; 😉&lt;/p&gt;

&lt;h2&gt;
  
  
  A bit of conception
&lt;/h2&gt;

&lt;p&gt;Before jumping straight to your keyboard and start coding, you have few things to consider, especially the switch's purpose. Indeed, a switch can be used in two ways:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;To turn on or off something (as you would do with a light switch)&lt;/li&gt;
&lt;li&gt;To select between two choices (a theme switcher, for example)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It's essential to know which use case is the right one for you because it impacts the underlying implementation. In our case, we're going to go for the first use case.&lt;/p&gt;

&lt;p&gt;Additionally, we want to label a toggle switch so that the user knows what is going to happen if he toggles the switch.&lt;/p&gt;

&lt;p&gt;Let's look at a real-world example where a user would choose to receive a newsletter. You can think of a first implementation where you would use a &lt;code&gt;checked&lt;/code&gt; prop, a &lt;code&gt;label&lt;/code&gt; prop and a &lt;code&gt;toggle&lt;/code&gt; event:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;Switch&lt;/span&gt;
  &lt;span class="na"&gt;:checked=&lt;/span&gt;&lt;span class="s"&gt;"shouldReceiveNewsletter"&lt;/span&gt;
  &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;toggle=&lt;/span&gt;&lt;span class="s"&gt;"toggle"&lt;/span&gt;
  &lt;span class="na"&gt;label=&lt;/span&gt;&lt;span class="s"&gt;"Receive newsletter"&lt;/span&gt;
&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;That's good. But we can achieve the same result by using &lt;a href="https://v3.vuejs.org/guide/component-custom-events.html#v-model-arguments" rel="noopener noreferrer"&gt;&lt;code&gt;v-model&lt;/code&gt;&lt;/a&gt; like so:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;Switch&lt;/span&gt; &lt;span class="na"&gt;v-model:checked=&lt;/span&gt;&lt;span class="s"&gt;"shouldReceiveNewsletter"&lt;/span&gt; &lt;span class="na"&gt;label=&lt;/span&gt;&lt;span class="s"&gt;"Receive newsletter"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;If you're familiar with Vue, you might be surprised with the use of &lt;code&gt;v-model&lt;/code&gt; in the example above. That's one of the changes introduced by Vue 3: you can now use an argument name directly on the template. The code above passes a &lt;code&gt;checked&lt;/code&gt; prop to &lt;code&gt;&amp;lt;Switch&amp;gt;&lt;/code&gt; that you can update by emitting an &lt;code&gt;update:checked&lt;/code&gt; event.&lt;/p&gt;
&lt;h2&gt;
  
  
  Build the template
&lt;/h2&gt;

&lt;p&gt;Whenever you have to choose HTML elements, you need to select the ones that make sense semantically. In our case, we'll have to use an &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input" rel="noopener noreferrer"&gt;&lt;code&gt;input&lt;/code&gt;&lt;/a&gt; as we're building a control. Remember, there are two use cases for a switch:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Switch a setting on/off: we need a &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/checkbox" rel="noopener noreferrer"&gt;checkbox&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Switching between one option and another (like a light/dark theme): we need two &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/radio" rel="noopener noreferrer"&gt;radio buttons&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We also need to make sure our input is labeled correctly. One way of doing so is to wrap an &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt; in a &lt;code&gt;&amp;lt;label&amp;gt;&lt;/code&gt; and add some text.&lt;/p&gt;

&lt;p&gt;Finally, we can also add an empty &lt;code&gt;&amp;lt;span&amp;gt;&lt;/code&gt; that we're going to use later to build our toggle switch. Go ahead and create a &lt;code&gt;Switch.vue&lt;/code&gt; file in which you can paste the following:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;template&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;label&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"checkbox"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;span&amp;gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;span&amp;gt;&lt;/span&gt;{{ label }}&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Props and v-model
&lt;/h2&gt;

&lt;p&gt;We need to pass two props to the Switch: &lt;code&gt;label&lt;/code&gt; which is a string and &lt;code&gt;checked&lt;/code&gt; which is a boolean. Remember that the &lt;code&gt;checked&lt;/code&gt; prop comes from &lt;code&gt;v-model:checked&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;template&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;label&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt;
      &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"checkbox"&lt;/span&gt;
      &lt;span class="na"&gt;:checked=&lt;/span&gt;&lt;span class="s"&gt;"checked"&lt;/span&gt;
      &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;change=&lt;/span&gt;&lt;span class="s"&gt;"$emit('update:checked', $event.target.checked)"&lt;/span&gt;
    &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;span&amp;gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;span&amp;gt;&lt;/span&gt;{{ label }}&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Switch&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;checked&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Boolean&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;There's a problem with the input above. Indeed, the root element is different than the underlying input. We have to create an additional prop for any other attribute we want to pass to the input (&lt;code&gt;disabled&lt;/code&gt;, for example).&lt;/p&gt;

&lt;p&gt;To fix it, we need to put a &lt;a href="https://v3.vuejs.org/api/instance-properties.html#attrs" rel="noopener noreferrer"&gt;&lt;code&gt;v-bind="$attrs"&lt;/code&gt;&lt;/a&gt; on the input and &lt;a href="https://v3.vuejs.org/guide/component-attrs.html#disabling-attribute-inheritance" rel="noopener noreferrer"&gt;disable attribute inheritance&lt;/a&gt; on the root element:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt;
  &lt;span class="na"&gt;v-bind=&lt;/span&gt;&lt;span class="s"&gt;"$attrs"&lt;/span&gt;
  &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"checkbox"&lt;/span&gt;
  &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;change=&lt;/span&gt;&lt;span class="s"&gt;"$emit('update:checked', $event.target.checked)"&lt;/span&gt;
  &lt;span class="na"&gt;:checked=&lt;/span&gt;&lt;span class="s"&gt;"checked"&lt;/span&gt;
&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Switch&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;inheritAttrs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="cm"&gt;/* ... */&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Style the component
&lt;/h2&gt;
&lt;h3&gt;
  
  
  The container and the label
&lt;/h3&gt;

&lt;p&gt;So far, our switch should look like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fot84bcqgrv2s5urtkm8s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fot84bcqgrv2s5urtkm8s.png" alt="A screenshot of an unstyled toggle switch" width="295" height="69"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's face it, it's ugly as hell. To make it prettier, we'll add CSS classes to the different elements:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;template&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"container"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt;
      &lt;span class="na"&gt;v-bind=&lt;/span&gt;&lt;span class="s"&gt;"$attrs"&lt;/span&gt;
      &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"input"&lt;/span&gt;
      &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"checkbox"&lt;/span&gt;
      &lt;span class="na"&gt;:checked=&lt;/span&gt;&lt;span class="s"&gt;"checked"&lt;/span&gt;
      &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;change=&lt;/span&gt;&lt;span class="s"&gt;"$emit('update:checked', $event.target.checked)"&lt;/span&gt;
    &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"switch"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"label"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;{{ label }}&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;We'll do them one by one. First, the &lt;code&gt;.container&lt;/code&gt;. We know the text will be on the right of the switch, and we want it to be perfectly centered. We also want the whole toggle to be clickable so let's add a pointer cursor to it:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;style &lt;/span&gt;&lt;span class="na"&gt;scoped&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nc"&gt;.container&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;pointer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;align-items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;We also need to give a prettier color to the label and give some space from the checkbox:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.label&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;margin-left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;12px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#1a202c&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Then, though we use the &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt; for semantic reasons, it won't be useful to us in terms of visuals. We need to hide it visually but still keep it in the DOM for accessibility reasons:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="c"&gt;/* Visually hide the checkbox input */&lt;/span&gt;
&lt;span class="nc"&gt;.input&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;absolute&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;-1px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;overflow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;hidden&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;clip&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;white-space&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;nowrap&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;em&gt;Note: the properties are inspired by the &lt;code&gt;.sr-only&lt;/code&gt; class from &lt;a href="https://tailwindcss.com/docs/screen-readers" rel="noopener noreferrer"&gt;Tailwind CSS&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  The switch
&lt;/h3&gt;

&lt;p&gt;The switch is composed of a rounded container element with a circle inside of it. This circle moves to the left or to the right depending on whether the input is checked or not.&lt;/p&gt;

&lt;p&gt;If you look at the screenshot, you can see that the inner circle is roughly half the size of the container element. The container width has twice the size of its own height. Let's make use of CSS custom properties for that:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.switch&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;--switch-container-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--switch-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--switch-container-width&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;/&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;To create the inner circle, we're going to use the &lt;code&gt;::before&lt;/code&gt; element trick. To make it inside the container, we'll need to give the container a &lt;code&gt;relative&lt;/code&gt; position and the inner circle an &lt;code&gt;absolute&lt;/code&gt; position.&lt;/p&gt;

&lt;p&gt;Additionally, the inner circle should be nearly the size of &lt;code&gt;--switch-size&lt;/code&gt; but it shouldn't overflow the container. We'll use the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/calc" rel="noopener noreferrer"&gt;&lt;code&gt;calc&lt;/code&gt;&lt;/a&gt; function to adjust it:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.switch&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;--switch-container-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--switch-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--switch-container-width&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;/&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c"&gt;/* Vertically center the inner circle */&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;align-items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;relative&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--switch-size&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;flex-basis&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--switch-container-width&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c"&gt;/* Make the container element rounded */&lt;/span&gt;
  &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--switch-size&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#e2e8f0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.switch&lt;/span&gt;&lt;span class="nd"&gt;::before&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;absolute&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c"&gt;/* Move a little bit the inner circle to the right */&lt;/span&gt;
  &lt;span class="nl"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--switch-size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;-&lt;/span&gt; &lt;span class="m"&gt;4px&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--switch-size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;-&lt;/span&gt; &lt;span class="m"&gt;4px&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c"&gt;/* Make the inner circle fully rounded */&lt;/span&gt;
  &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;9999px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;white&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Here is the result:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fva5cyfru8d5r5l0buf3i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fva5cyfru8d5r5l0buf3i.png" alt="A screenshot of a styled switch but not functional" width="295" height="76"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That's nice, but if you click on the switch nothing happens. At least, visually. Indeed, the input is checked correctly, but your switch isn't connected to it!&lt;/p&gt;

&lt;p&gt;To reflect these changes, you'll need to use the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Adjacent_sibling_combinator" rel="noopener noreferrer"&gt;CSS adjacent sibling selector&lt;/a&gt;, which is &lt;code&gt;+&lt;/code&gt;, to style the switch according to the different input states. For example, when your checkbox is checked, the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/:checked" rel="noopener noreferrer"&gt;&lt;code&gt;:checked&lt;/code&gt;&lt;/a&gt; pseudo-class is added. Let's make use of that then:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.input&lt;/span&gt;&lt;span class="nd"&gt;:checked&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nc"&gt;.switch&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/* Teal background */&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#4fd1c5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.input&lt;/span&gt;&lt;span class="nd"&gt;:checked&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nc"&gt;.switch&lt;/span&gt;&lt;span class="nd"&gt;::before&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;border-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#4fd1c5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c"&gt;/* Move the inner circle to the right */&lt;/span&gt;
  &lt;span class="nl"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;translateX&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--switch-container-width&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;-&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--switch-size&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The way the switch moves from one state to another isn't smooth. We need to add transitions to &lt;code&gt;transform&lt;/code&gt; and &lt;code&gt;background-color&lt;/code&gt; to fix it:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.switch&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/* ... */&lt;/span&gt;
  &lt;span class="nl"&gt;transition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;background-color&lt;/span&gt; &lt;span class="m"&gt;0.25s&lt;/span&gt; &lt;span class="n"&gt;ease-in-out&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.switch&lt;/span&gt;&lt;span class="nd"&gt;::before&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/* ... */&lt;/span&gt;
  &lt;span class="nl"&gt;transition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;transform&lt;/span&gt; &lt;span class="m"&gt;0.375s&lt;/span&gt; &lt;span class="n"&gt;ease-in-out&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  The focus and disabled states
&lt;/h3&gt;

&lt;p&gt;Right now, you should have a switch that works. But the work isn't entirely done yet! Indeed, there are still different states to an input that we haven't implemented here. For example, if you press the &lt;code&gt;Tab&lt;/code&gt; key to focus the switch, you don't have any visual feedback that it's properly focused. The same goes for disabled inputs.&lt;/p&gt;

&lt;p&gt;As a first step, we're going to add additional CSS custom properties to &lt;code&gt;.switch&lt;/code&gt; and replace the hardcoded colors:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.switch&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/* ... */&lt;/span&gt;

  &lt;span class="py"&gt;--light-gray&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#e2e8f0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--gray&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#cbd5e0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--dark-gray&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#a0aec0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--teal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#4fd1c5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--dark-teal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#319795&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c"&gt;/* ... */&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--light-gray&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.input&lt;/span&gt;&lt;span class="nd"&gt;:checked&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nc"&gt;.switch&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--teal&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.input&lt;/span&gt;&lt;span class="nd"&gt;:checked&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nc"&gt;.switch&lt;/span&gt;&lt;span class="nd"&gt;::before&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;border-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--teal&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c"&gt;/* ... */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;em&gt;Note: the colors come from &lt;a href="https://tailwindcss.com/docs/background-color" rel="noopener noreferrer"&gt;Tailwind CSS&lt;/a&gt; in case you're wondering.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Let's tackle the focus state. We're not going to do anything complicated UI-wise, we'll just have to add a border on the inner circle:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.switch&lt;/span&gt;&lt;span class="nd"&gt;::before&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/* ... */&lt;/span&gt;
  &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--light-gray&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Here, we chose the same color as the background of the switch container. Indeed, initially, we want the inner circle border color to confound with the background color. That way, when we adding a different &lt;code&gt;border-color&lt;/code&gt; for the focus state, we'll be able to see it. We're going to add a darker &lt;code&gt;border-color&lt;/code&gt; when the input is focused:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.input&lt;/span&gt;&lt;span class="nd"&gt;:focus&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nc"&gt;.switch&lt;/span&gt;&lt;span class="nd"&gt;::before&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;border-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--dark-gray&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.input&lt;/span&gt;&lt;span class="nd"&gt;:focus:checked&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nc"&gt;.switch&lt;/span&gt;&lt;span class="nd"&gt;::before&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;border-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--dark-teal&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Here's how it looks:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq5z5kb9fd7oy9fssorea.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq5z5kb9fd7oy9fssorea.png" alt="A screenshot of a switch with focus" width="320" height="128"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For the disabled state, we're going to fill the inner circle with gray and make the switch container darker to indicate that you can't do anything on it:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.input&lt;/span&gt;&lt;span class="nd"&gt;:disabled&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nc"&gt;.switch&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--gray&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.input&lt;/span&gt;&lt;span class="nd"&gt;:disabled&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nc"&gt;.switch&lt;/span&gt;&lt;span class="nd"&gt;::before&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--dark-gray&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;border-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--dark-gray&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Here's what our disabled switch looks like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0bkdin50l8ug43nsbhdp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0bkdin50l8ug43nsbhdp.png" alt="A screenshot of a switch that is disabled" width="302" height="76"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  The switch's responsiveness
&lt;/h3&gt;

&lt;p&gt;We have one last thing to check. Look at the screenshot below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuwkzs1x29nif1ba0m9jq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuwkzs1x29nif1ba0m9jq.png" alt="A screenshot of a switch that is not responsive" width="378" height="101"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you have a long label, you can see that the text overflows on the switch and may take multiple lines. That's not responsive, is it? Let's make sure our switch can't shrink, and the label doesn't take more than one line:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.switch&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/* ... */&lt;/span&gt;
  &lt;span class="c"&gt;/* In case the label gets long, the toggle shouldn't shrink. */&lt;/span&gt;
  &lt;span class="nl"&gt;flex-shrink&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.label&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/* ... */&lt;/span&gt;
  &lt;span class="c"&gt;/* Show an ellipsis if the text takes more than one line */&lt;/span&gt;
  &lt;span class="nl"&gt;overflow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;hidden&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;text-overflow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ellipsis&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;white-space&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;nowrap&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now, our switch is responsive:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F97kd307pjsl3a2wu87ij.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F97kd307pjsl3a2wu87ij.png" alt="A screenshot of a switch that is responsive" width="368" height="93"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Voilà! We're done for the switch. The switch is a small piece of UI, but it's not that easy to implement. Here are the main takeaways when building such a component:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Think of your component's API beforehand and its use cases. You'll have a better vision of what you want to build.&lt;/li&gt;
&lt;li&gt;Don't forget to think of the different constraints of a UI component: its accessibility, its various states, its responsiveness, etc.&lt;/li&gt;
&lt;li&gt;Build your component step by step. You should have an iterative approach with these kinds of components.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In case, you want to have the full code, I put it in a GitHub Gist that you can find below. How nice is that? 😄&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



</description>
      <category>vue</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>How do you find time for your side projects?</title>
      <dc:creator>Thomas Lombart</dc:creator>
      <pubDate>Mon, 18 May 2020 17:33:10 +0000</pubDate>
      <link>https://dev.to/thomaslombart/how-do-you-find-time-for-your-side-projects-i2g</link>
      <guid>https://dev.to/thomaslombart/how-do-you-find-time-for-your-side-projects-i2g</guid>
      <description>&lt;p&gt;It's common for a developer to have side-projects, whether it's a blog, an app to build, an open-source library to maintain, or a course to watch or read. Aside from a full-time job, it can be hard to dedicate time to them.&lt;/p&gt;

&lt;p&gt;Often, I like to get up one hour early and work on it. I often find myself working on Saturday morning if I feel like it. What about you? What are your strategies, tips and tricks to manage your time for your side projects?&lt;/p&gt;

</description>
      <category>discuss</category>
    </item>
    <item>
      <title>Over 20 Resources to Advance Your JavaScript Skills</title>
      <dc:creator>Thomas Lombart</dc:creator>
      <pubDate>Mon, 04 May 2020 16:39:55 +0000</pubDate>
      <link>https://dev.to/thomaslombart/20-resources-to-read-or-watch-to-become-an-advanced-javascript-developer-18hb</link>
      <guid>https://dev.to/thomaslombart/20-resources-to-read-or-watch-to-become-an-advanced-javascript-developer-18hb</guid>
      <description>&lt;p&gt;JavaScript has never been more used than today. It's a real asset to get good at it. When discovering JavaScript, you first learn variables, if statements, loops, arrays, objects, functions! Maybe you even know what is &lt;code&gt;this&lt;/code&gt; and how to use &lt;code&gt;async/await&lt;/code&gt;.&lt;br&gt;
But that's just the tip of the iceberg. There's more to JavaScript you need to learn.&lt;/p&gt;

&lt;p&gt;To better understand JavaScript, you need to deeply understand its foundations and how it works under the hood. That can be a daunting task. But don't worry, I got your back!&lt;br&gt;
I read and watched many resources to get better at JavaScript, and I want to share that with you today.&lt;/p&gt;

&lt;h2&gt;
  
  
  Topics to learn
&lt;/h2&gt;

&lt;p&gt;To level-up your JavaScript skills, you'll need to know:&lt;/p&gt;

&lt;h3&gt;
  
  
  What is JavaScript
&lt;/h3&gt;

&lt;p&gt;Multi-paradigm, dynamically typed, single-threaded, ECMAScript specification. You need to know what makes JS JS. Kyle Simpson explained it in the &lt;a href="https://github.com/getify/You-Dont-Know-JS/blob/2nd-ed/get-started/ch1.md" rel="noopener noreferrer"&gt;first chapter&lt;/a&gt; of You Don't Know JS Yet.&lt;/p&gt;

&lt;h3&gt;
  
  
  How the JavaScript engine works
&lt;/h3&gt;

&lt;p&gt;To run code, you need an engine to run it. Lydia Hallie explained it well in this post about the &lt;a href="https://dev.to/lydiahallie/javascript-visualized-the-javascript-engine-4cdf"&gt;JavaScript engine&lt;/a&gt;. You'll realize how typing JavaScript can make it more performant for v8.&lt;/p&gt;

&lt;h3&gt;
  
  
  The dreaded event loop
&lt;/h3&gt;

&lt;p&gt;Did you know that JavaScript executes synchronously? But then how can you make API calls and still not block the page? Introducing the event loop and browser APIs. There are two excellent videos on that: &lt;a href="https://www.youtube.com/watch?v=cCOL7MC4Pl0" rel="noopener noreferrer"&gt;In The Loop&lt;/a&gt; from Jake Archibald and &lt;a href="https://www.youtube.com/watch?v=8aGhZQkoFbQ" rel="noopener noreferrer"&gt;What the heck is the event loop anyway&lt;/a&gt; from Philip Roberts.&lt;/p&gt;

&lt;h3&gt;
  
  
  Execution context, hoisting, scopes and closures
&lt;/h3&gt;

&lt;p&gt;You need to know what JavaScript actually does when running a program. For that Tyler Mc Ginnis got your back with an awesome post on &lt;a href="https://tylermcginnis.com/ultimate-guide-to-execution-contexts-hoisting-scopes-and-closures-in-javascript/" rel="noopener noreferrer"&gt;execution context, hoisting, scopes and closures&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Coercion
&lt;/h3&gt;

&lt;p&gt;What actually happens when JavaScript interprets &lt;code&gt;"1" == 1&lt;/code&gt;? Hint: coercion. Alexey Samoshkin wrote a &lt;a href="https://www.freecodecamp.org/news/js-type-coercion-explained-27ba3d9a2839/" rel="noopener noreferrer"&gt;guide on JavaScript coercion&lt;/a&gt; that's really interesting!&lt;/p&gt;

&lt;h3&gt;
  
  
  Prototypes in JavaScript
&lt;/h3&gt;

&lt;p&gt;This is a JavaScript pillar that you can't escape, so you better learn what it means. I found two useful posts on that: &lt;a href="https://medium.com/better-programming/prototypes-in-javascript-5bba2990e04b" rel="noopener noreferrer"&gt;Prototypes in JavaScript&lt;/a&gt; from Rupesh Mishra and &lt;a href="https://tylermcginnis.com/beginners-guide-to-javascript-prototype/" rel="noopener noreferrer"&gt;A Beginner's Guide to JavaScript's Prototype&lt;/a&gt; from Tyler McGinnis. Hopefully, with these articles, the prototype chain, &lt;code&gt;__proto__&lt;/code&gt; and objects won't be scary anymore.&lt;/p&gt;

&lt;h3&gt;
  
  
  This, call, apply and bind
&lt;/h3&gt;

&lt;p&gt;Ah, &lt;code&gt;this&lt;/code&gt;. With a misunderstanding of &lt;code&gt;this&lt;/code&gt;, you can often get common errors like &lt;code&gt;Cannot read property 'name' of undefined&lt;/code&gt; or &lt;code&gt;greet is not a function&lt;/code&gt; in your programs. Tania Rascia broke down these concepts for you in her post &lt;a href="https://www.taniarascia.com/this-bind-call-apply-javascript/" rel="noopener noreferrer"&gt;Understanding This, Bind, Call, and Apply in JavaScript&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Promises and async/await
&lt;/h3&gt;

&lt;p&gt;ES2015 made JavaScript developers' lives more comfortable by bringing promises that allowed you to write simpler asynchronous code. Learn what they mean by reading &lt;a href="https://medium.com/javascript-scene/master-the-javascript-interview-what-is-a-promise-27fc71e77261" rel="noopener noreferrer"&gt;What is a Promise?&lt;/a&gt; from Eric Elliott or &lt;a href="https://scotch.io/tutorials/javascript-promises-for-dummies" rel="noopener noreferrer"&gt;JavaScript Promises for Dummies&lt;/a&gt; on Scotch.io. You can also watch a great talk from Wes Bos on &lt;a href="https://www.youtube.com/watch?v=DwQJ_NPQWWo" rel="noopener noreferrer"&gt;Async/Await&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Modules
&lt;/h3&gt;

&lt;p&gt;What are ECMAScript modules? Common JS? A module bundler? Find the answers in yet another post from Tyler Mc Ginnis on &lt;a href="https://tylermcginnis.com/javascript-modules-iifes-commonjs-esmodules/" rel="noopener noreferrer"&gt;JavaScript Modules&lt;/a&gt;. I also highly recommend that you check out &lt;a href="https://frontendmasters.com/courses/webpack-fundamentals/" rel="noopener noreferrer"&gt;this course on Webpack 4 fundamentals&lt;/a&gt; from Sean Larkin.&lt;/p&gt;

&lt;h3&gt;
  
  
  Functional programming
&lt;/h3&gt;

&lt;p&gt;We already know that JavaScript is a multi-paradigm language. One paradigm supported in JavaScript is functional programming since functions are first-class citizens. Andrea Bertoli made an excellent post on &lt;a href="https://dev.to/mr_bertoli/an-adequate-introduction-to-functional-programming-1gcl"&gt;the basics of functional programming&lt;/a&gt;. You'll see the power of composition.&lt;/p&gt;

&lt;h2&gt;
  
  
  Courses
&lt;/h2&gt;

&lt;p&gt;There are many resources for learning JavaScript, as you saw above, and it may be overwhelming. Don't worry. If you prefer to get a single course, I got your back too:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://tylermcginnis.com/courses/advanced-javascript/" rel="noopener noreferrer"&gt;Advanced JavaScript&lt;/a&gt; from Tyler Mc Ginnis: I used many resources from him previously. That's because he has a whole course on that. It'll make you, for sure, a more proficient JavaScript developer.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.udemy.com/course/advanced-javascript-concepts/" rel="noopener noreferrer"&gt;Advanced JavaScript Concepts&lt;/a&gt; from Andrei Neagoie: he has released many popular courses before this one. You'll find anything you need to know to become an advanced JS developer.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dev.to/lydiahallie/javascript-visualized-event-loop-3dif"&gt;JavaScript Visualized&lt;/a&gt; from Lydia Hallie: she wrote many posts on JavaScript concepts with remarkable visual explanations. I highly recommend it.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://frontendmasters.com/courses/javascript-hard-parts-v2/" rel="noopener noreferrer"&gt;JavaScript: the Hard Parts&lt;/a&gt; from Will Sentance. This great workshop will make the hard parts of JavaScript easier for you. To go further, you can watch the following two workshops from Will too: &lt;a href="https://frontendmasters.com/courses/object-oriented-js/" rel="noopener noreferrer"&gt;JavaScript: The Hard Parts of Object-Oriented JavaScript&lt;/a&gt; and &lt;a href="https://frontendmasters.com/courses/javascript-new-hard-parts/" rel="noopener noreferrer"&gt;JavaScript: The New Hard Parts&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When you have to learn new concepts, you need to space your learning in time, read or watch different resources and practice a lot. Using this strategy allows you to truly master a topic. That's why I recommended various posts and courses. Don't wait and start to get better at JavaScript!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How to Suck Less at Colors as a Developer</title>
      <dc:creator>Thomas Lombart</dc:creator>
      <pubDate>Mon, 27 Apr 2020 10:29:16 +0000</pubDate>
      <link>https://dev.to/thomaslombart/make-your-colors-great-again-4if</link>
      <guid>https://dev.to/thomaslombart/make-your-colors-great-again-4if</guid>
      <description>&lt;p&gt;&lt;em&gt;This post has been co-written with &lt;strong&gt;Esther Boulanger&lt;/strong&gt; who is UI designer. Many thanks to her for helping me with the content and the drawings!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;What comes first to your mind when you think about design? The first thing that pops into my head is colors. Colors are everywhere and essential for design.&lt;/p&gt;

&lt;p&gt;Working with colors seems simple. At least, until you have to design a user interface and choose your color palette. At that moment, you have writer's block but applied for design. You try to do stuff, but nothing ever looks good. After a while, you think that, who cares? You're not one of these design magicians. You just suck at design. I've been there.&lt;/p&gt;

&lt;p&gt;However, it's useful to know at least the fundamentals of what makes a user interface great. And, whether you like it or not, colors are an essential component of it. Without further ado, let's look at how you can use colors in your UI and much more!&lt;/p&gt;

&lt;h2&gt;
  
  
  Color formats
&lt;/h2&gt;

&lt;p&gt;There are a lot of formats for colors. The most popular ones are Hex, RGB, HSB, and HSL. Let me explain the differences between them and which one you should use. 🧐&lt;/p&gt;

&lt;h3&gt;
  
  
  Hex and RGB
&lt;/h3&gt;

&lt;p&gt;RGB and Hex are the most common formats for representing colors.&lt;/p&gt;

&lt;p&gt;RGB gives us the intensity of red, green, and blue of one color. Intensity is a number that can go from 0 to 255. As an example, you could define a light purple color with 164 of red, 43 of green, and 217 of blue:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.color&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;rgb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;164&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;43&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;217&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hex stands for hexadecimal. It's similar to RGB, only the format changes: &lt;code&gt;#RRGGBB&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;As with RGB, R is for the intensity of red, G for green, and B for blue. These values can go from 00 to FF (which means 0 to 255 if you convert it to decimal). For example, &lt;code&gt;#FF0000&lt;/code&gt; represents a pure red. Indeed, &lt;code&gt;#FF&lt;/code&gt; means red is at its highest intensity (255), and the others are at their lowest.&lt;/p&gt;

&lt;p&gt;I'll say it upfront, those two formats aren't the best when you have to pick colors. Indeed, let's say you want your app to have a blue primary color. You won't have only one blue, right? You'll have to make a lighter blue or a darker blue. Well, good luck doing that with RGB and Hex!&lt;/p&gt;

&lt;p&gt;Note: RGB and Hex are not suitable for &lt;strong&gt;picking&lt;/strong&gt; colors, but you can still use them for &lt;strong&gt;representing&lt;/strong&gt; colors.&lt;/p&gt;

&lt;p&gt;That being said, let me introduce you to HSB, HSL, and their differences. Let's begin with HSB.&lt;/p&gt;

&lt;h3&gt;
  
  
  HSB
&lt;/h3&gt;

&lt;p&gt;HSB means hue, saturation, and brightness.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;H stand for &lt;strong&gt;Hue&lt;/strong&gt;. It's a number measured in degrees that is between 0 and 360. The following drawing speaks for itself:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb4x01ufi898tv9vqfi7m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb4x01ufi898tv9vqfi7m.png" alt="Color wheel" width="375" height="285"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you have a visual memory and want to pick a color, this drawing will be your best friend.&lt;/p&gt;

&lt;p&gt;What about saturation and brightness? For that, let's take a look at the following drawing:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpwpnoqb7xjhllw8udfxw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpwpnoqb7xjhllw8udfxw.png" alt="Four circles tainted of blue" width="348" height="176"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These 4 circles all have the same hue (210°), but still, they look different. Well, that's because of &lt;strong&gt;saturation&lt;/strong&gt; and &lt;strong&gt;brightness&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;S stands for &lt;strong&gt;Saturation&lt;/strong&gt;. It's a percentage representing how vibrant color is. 0% means you have no saturation, while 100% means you have the maximum. If you choose to add a blue to your UI with a hue of 210° and saturation of 0%, you'll get a gray color. High saturation, vibrant color. Low saturation, dull color.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To better visualize the saturation for color, here is the blue we saw above with different variations:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxvibyf7plwos8dc57xau.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxvibyf7plwos8dc57xau.png" alt="Saturation variations of blue" width="531" height="359"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;B stand for &lt;strong&gt;Brightness&lt;/strong&gt;. It's a percentage representing how bright a color is. Basically, the higher is the brightness, the more your eyes will suffer in the dark. If the brightness is at 0%, you'll get black no matters the hue or saturation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, you can get two different results for brightness at 100% depending on the saturation:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;If the saturation is at 0%, you'll get pure white.&lt;/li&gt;
&lt;li&gt;If you have a saturation different than 0%, you'll just get a highly-bright color that is more or less vibrant.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbosvfy50osnz5q4r83mq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbosvfy50osnz5q4r83mq.png" alt="Color picker annotated" width="591" height="484"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The most perceptive of you will think that, OK, HSB is great, but you can't work with HSB in CSS. Instead, CSS supports HSL. Let's see it right away.&lt;/p&gt;

&lt;h3&gt;
  
  
  HSL
&lt;/h3&gt;

&lt;p&gt;HSL means hue, saturation and lightness. Thus, the only difference compared to HSB here is the lightness.&lt;/p&gt;

&lt;p&gt;Lightness represents how close a color is to black or white.&lt;br&gt;
0% lightness is equal to black (like the brightness), BUT 100% lightness is equivalent to white &lt;strong&gt;no matter the hue or the saturation&lt;/strong&gt;. This is the big difference between brightness and lightness.&lt;/p&gt;

&lt;p&gt;Let's take a value example with HSB and HSL. We'll take a hue of 250° (darker blue) and a saturation of 75% (very vibrant).&lt;/p&gt;

&lt;p&gt;For HSB, you'll get:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;H=250, S=75%, B=0% → black&lt;/li&gt;
&lt;li&gt;H=250, S=75%, B=100% → very bright blue&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For HSL, you'll get:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;H=250, S=75%, L=0% → black&lt;/li&gt;
&lt;li&gt;H=250, S=75%, L=50% → very bright blue (the same as with HSB)&lt;/li&gt;
&lt;li&gt;H=250, S=75%, L=100% → white&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There's something I find weird with HSL while designing. When I move the lightness up or down and convert it to HSB, the saturation isn't the same. For that reason, I prefer to work with HSB that seems easier to me.&lt;/p&gt;

&lt;p&gt;In the end, it doesn't matter if HSB is not available in CSS. What you can do is to pick your colors upfront with HSB and convert them to hexadecimal values.&lt;/p&gt;

&lt;p&gt;You know about color formats. Great. Let's deep dive into the exciting stuff.&lt;/p&gt;

&lt;h2&gt;
  
  
  Color variation
&lt;/h2&gt;

&lt;p&gt;Don't trust the tools that magically gives you a palette with 4-5 different colors, it won't work. What you need to learn instead is how to make color variations. Trust me, with gray and a primary color, you can already make pretty good UIs. Look at the apps and websites around you; they usually have one primary color, and still, they look good.&lt;/p&gt;

&lt;p&gt;To create color variations, you first have to play with the hue. Indeed, there are 360 shades of colors different in the color wheel. You can get a lot of colors just with the hue. Let's take an example of green color with a saturation of 100% and a brightness of 70% (very vibrant and bright).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7ubir3cayeperfgz6nro.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7ubir3cayeperfgz6nro.png" alt="Green color variation" width="337" height="162"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here are the different values of these three circles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;First circle: H=120°. I get green.&lt;/li&gt;
&lt;li&gt;Second circle: H=156°. I get a green that tends towards the blue.&lt;/li&gt;
&lt;li&gt;Third circle: H=80°. I get a green that tends towards the yellow.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Play with different colors and see what works well or not. Indeed, in design, you have to &lt;strong&gt;TRY&lt;/strong&gt; many things to determine what you really want, what is best for you.&lt;/p&gt;

&lt;p&gt;OK. So hue allows us to modify the tone of the color, what about saturation and brightness?&lt;/p&gt;

&lt;h2&gt;
  
  
  Create lighter or darker colors with saturation and brightness
&lt;/h2&gt;

&lt;p&gt;Most of the time, you'll want to use saturation and brightness to create lighter or darker colors. Let's start with a darker color.&lt;/p&gt;

&lt;p&gt;In your opinion, what would you have to do to have a darker color? You'd probably think we would just have to tune the brightness down, right?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnky1l9b3aicb0xwfjema.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnky1l9b3aicb0xwfjema.png" alt="Color picker showing how to get a darker color with brightness" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Well, let's try that on an example:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxbvcv1u0ami21ff59q75.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxbvcv1u0ami21ff59q75.png" alt="Dark green variation too dark" width="800" height="496"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is what you can get by using this method. Take a look at the last two greens. They're way too dark! Indeed, by only decreasing the brightness, your color also gets less colorful. We can fix it by increasing the saturation:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb5l8q5xr2d2r0ljnfbam.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb5l8q5xr2d2r0ljnfbam.png" alt="Color picker showing how to get a darker color with brightness and saturation" width="800" height="730"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's try again:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxpht1df177yc92a3k06u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxpht1df177yc92a3k06u.png" alt="Right dark green variation" width="800" height="399"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Look at these new shades of green: that's way better!&lt;/p&gt;

&lt;p&gt;For a lighter color, you need to do all the contrary: increase the brightness and decrease the saturation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffhcpf4ebf1epw4i46pdh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffhcpf4ebf1epw4i46pdh.png" alt="Color picker showing how to get a lighter color" width="800" height="794"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's take an indigo color and create lighter variations:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq8450q5kltscj1bsgtrb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq8450q5kltscj1bsgtrb.png" alt="Indigo lighter variations" width="800" height="465"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By increasing the brightness and decreasing the saturation, you get lighters blue.&lt;/p&gt;

&lt;p&gt;So, remember:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Darker color = saturation up, brightness down&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Lighter color = saturation down, brightness up&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Congratulations, you just unlocked the power of color variations! 😎&lt;/p&gt;

&lt;p&gt;You can also move the hue up or down along saturation and brightness to get lighter or darker colors. There are no magical formulas for creating color variations. The key is to adjust your values until it looks good to you. I know, &lt;em&gt;easier said than done&lt;/em&gt;, but at least you know how to easily make a color darker or lighter. 😏&lt;/p&gt;

&lt;h2&gt;
  
  
  Choosing colors
&lt;/h2&gt;

&lt;p&gt;Don't get me wrong, as of today, I still struggle with colors. However, I learned some things along the way. You'll find below a handful of color tips that I think will be useful to you.&lt;/p&gt;

&lt;h3&gt;
  
  
  Gray
&lt;/h3&gt;

&lt;p&gt;When you design UIs, you need to understand that &lt;strong&gt;gray is essential.&lt;/strong&gt; Before choosing colors, you need to design your applications only with different shades of gray.&lt;/p&gt;

&lt;p&gt;Once done, you can think of colors. However, don't paint your whole app, only apply colors where that's necessary: for the navigation bar, buttons, backgrounds, maybe on some words but not everywhere! The more I look at stunning designs, the more I realize they're really subtle.&lt;/p&gt;

&lt;h3&gt;
  
  
  Picking colors
&lt;/h3&gt;

&lt;p&gt;You probably ask yourself how to pick colors. You're not going to like this answer, but it depends. Usually, you can consider that one or two colors are enough! Stick with them and use them sparingly.&lt;/p&gt;

&lt;p&gt;If you already have a logo, you can pick its primary color since it's your brand's main color. For example, facebook's logo is a blue F. Let's take a look at their UI:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj151ck8v6anpx5lpcmfv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj151ck8v6anpx5lpcmfv.png" alt="Facebook homepage" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can notice that the same blue is used everywhere but with different variations. One color and it looks good! Note also that the rest of the app is made of gray. 😉&lt;/p&gt;

&lt;p&gt;Blue is a great starter color. Be careful though, it tends to be overused. We saw above that Facebook uses blue, but it's not the only one, far from it. Twitter also uses it as an example!&lt;/p&gt;

&lt;p&gt;Choose your colors according to your brand and your audience. For example, if you're designing a bank app, you'll probably want to choose sober colors since it inspires professionalism. On the contrary, if you want to make your app playful, such as the famous Duolingo, choosing vibrant colors (saturation, remember?) will be a great choice:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdxilr6hafwt777b7aw8n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdxilr6hafwt777b7aw8n.png" alt="A screenshot of Duolingo" width="800" height="453"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: the content is in French, but nevermind we're looking at the UI, right?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Don't make the obvious choice. It's not because you're designing for ecology that you have to choose green colors. Sometimes, selecting original colors can make your app stand out!&lt;/p&gt;

&lt;h3&gt;
  
  
  Gradients
&lt;/h3&gt;

&lt;p&gt;If you’re not satisfied with a particular color, you can use gradients. Here are different gradients:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnrqhw08xip0jpykppfyf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnrqhw08xip0jpykppfyf.png" alt="Different use of gradients" width="800" height="684"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It's not that hard to create one. Choose a color and make the second one lighter or darker. I also find gradients to look better when the second color has a different hue. So, when creating gradients, it's fine to tune everything: hue, saturation and brightness.&lt;/p&gt;

&lt;p&gt;Here's an example of a design made by &lt;a href="https://dribbble.com/shots/8660936-Birds-Guide-APP" rel="noopener noreferrer"&gt;Walid Beno on Dribbble&lt;/a&gt;. He makes use of gradients on the background and buttons. The result is stunning:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg3bbhflm0x346v6zcjc2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg3bbhflm0x346v6zcjc2.png" alt="Illustration of a UI with gradients" width="800" height="593"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Secondary colors
&lt;/h3&gt;

&lt;p&gt;Most of the time, you'll still want to have a secondary color in your application. Something that works great is to &lt;strong&gt;associate a cold color with a warm color&lt;/strong&gt;: purple with orange, red with blue, yellow, with blue, whatever! Here's an example of a design made by &lt;a href="https://dribbble.com/shots/7079177-Bengkelan-The-Auto-Mechanic-That-Comes-To-You-Website-Concept" rel="noopener noreferrer"&gt;Sight Setyo Nugroho for OWW on Dribbble&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgzlajgx68a30z1o6z43u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgzlajgx68a30z1o6z43u.png" alt="Illustration of a UI with a warm and cold color" width="800" height="560"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Dark interfaces
&lt;/h3&gt;

&lt;p&gt;You may want to go with a dark interface. Obviously, your app will be filled with black or dark gray. In this situation, choose colors that are highly-contrasted with dark (so, high saturation). Usually, yellow, orange, or purple (but not too dark) look great. Here's an example &lt;a href="https://dribbble.com/shots/10090105-Dashboard-UI" rel="noopener noreferrer"&gt;by DStudio on Dribbble&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqr17ze4hnlxrf52ir2yv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqr17ze4hnlxrf52ir2yv.png" alt="Dark interface" width="800" height="507"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Design isn't easy. Picking colors isn't easy. Even creating color variations isn't easy. The more you design, the better you get. There are rules in design that you can leverage to build great UIs, as we saw with color variations. But, it won't magically make you a design master. At first, you will suck. But after producing dozens of designs and lots of color variations, you'll start to get better at it.&lt;/p&gt;

</description>
      <category>design</category>
      <category>css</category>
    </item>
    <item>
      <title>Why Learning Design Is Important for Front-End Developers</title>
      <dc:creator>Thomas Lombart</dc:creator>
      <pubDate>Mon, 20 Apr 2020 11:09:22 +0000</pubDate>
      <link>https://dev.to/thomaslombart/why-learning-design-is-important-for-front-end-developers-28gk</link>
      <guid>https://dev.to/thomaslombart/why-learning-design-is-important-for-front-end-developers-28gk</guid>
      <description>&lt;p&gt;A few months ago, I decided to learn UI and UX design. I've always been impressed at stunning mockups I saw on &lt;a href="https://dribbble.com/" rel="noopener noreferrer"&gt;Dribbble&lt;/a&gt;. So, I thought it would be great to get a glimpse of what you need to do to achieve great designs. I made this decision with pure curiosity. Along the way, I learned about colors, spacing, typography, and more!&lt;/p&gt;

&lt;p&gt;By reflecting on what I learned, I realized something: &lt;strong&gt;learning design is essential for front-end developers.&lt;/strong&gt; In the end, it's our task to give life to mockups, to make them interactive. Thus, why not learning how to design the user interface itself?&lt;/p&gt;

&lt;p&gt;Let's see what learning design can bring you in terms of benefits.&lt;/p&gt;

&lt;h2&gt;
  
  
  Better value in your team
&lt;/h2&gt;

&lt;p&gt;There's a standard workflow you can find across tech companies (especially start-ups). They have product owners and managers, a design team, a development team (both front-end and back-end). The product owners think of the new features with the team. The designer produces mockups. The back-end developers provide the endpoints to call. You, front-end developers, are responsible for making the mockups alive.&lt;/p&gt;

&lt;p&gt;In an ideal world, you have a design team, and they think of all the edge cases you can encounter:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When you have no data to display (empty state)&lt;/li&gt;
&lt;li&gt;When you have an error&lt;/li&gt;
&lt;li&gt;When an input gets really long.&lt;/li&gt;
&lt;li&gt;Etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In real life, you don't necessarily have a design team, and when you have one, they're not always available because they have a lot of work. In this case, you can sometimes be blocked. It may be because the mockups are missing or because you want the opinion of one of your fellow designers that are not available at the moment.&lt;/p&gt;

&lt;p&gt;Knowing design is a considerable value for your team. It doesn't mean you have to replace the designer's work. On the contrary, it can even be complementary. You can build a basic design if you need to do a proof of concept for something your company wants to test. Or, if your designer forgets an edge case, you can also handle it without waiting for their input.&lt;/p&gt;

&lt;p&gt;It also means you're more efficient when building UIs. You are quicker and more detailed. I often see developers who blindly copy-paste the values they get from Zeplin or InVision mockups. The thing is, these values can be incorrect, and it results in inconsistencies in your app. When you know how it's actually made off, you don't fall into these traps.&lt;/p&gt;

&lt;p&gt;Furthermore, knowing to design can be a great asset in case of negotiation. You can bring up the fact that you can cover the technical part of a project and the design part, which, ultimately, results in fewer costs for the company and higher benefits for you. It's what we call a win-win.&lt;/p&gt;

&lt;h2&gt;
  
  
  Better side-projects design
&lt;/h2&gt;

&lt;p&gt;That's the most important thing for me: designing for side-projects. Whether it's an app, a blog post, open-source work, videos, or whatever I can think of, there's always a time when you need to do design work.&lt;/p&gt;

&lt;p&gt;For example, I was able to do all the design of this blog by myself. It's not incredibly beautiful, but I think it looks good and does the work. Without design in my toolbelt, I'm not sure it would have been the same.&lt;/p&gt;

&lt;p&gt;Knowing how to code and how to design also makes you more independent. You can basically handle your whole website/app in terms of how it looks. It's like unlocking new powers because not only can you build something useful and interactive, but you can also make it look great!&lt;/p&gt;

&lt;h2&gt;
  
  
  Better communication with designers
&lt;/h2&gt;

&lt;p&gt;Communication in a team is vital. I've already written about it in a previous blog post about &lt;a href="https://thomaslombart.com/soft-skills-developers/" rel="noopener noreferrer"&gt;soft skills&lt;/a&gt;. A front-end developer will have to communicate with its colleagues, back-end developers, product owners, managers, and designers! When you go along with a designer and that you truly work together, it can do wonders in your team.&lt;/p&gt;

&lt;p&gt;Indeed, I'm sure you already got a stunning mockup that was really complex to build. If it ever happens, please, don't complain. Don't shout out loud that the designer is dumb, is not realistic, and knows nothing about code. Instead, cooperate and think of an alternative solution.&lt;/p&gt;

&lt;p&gt;Once, I told a designer an alternative solution to a feature, and his reaction was, &lt;em&gt;"Oh, it's actually possible to do this? I didn't go with this in the first place because I thought it was too hard for you"&lt;/em&gt;. Being proactive and using your design skills in these situations can save time and, consequently, money (and companies like you when you're saving money for them).&lt;/p&gt;

&lt;p&gt;Another case when you can use both your communication and design skills is when you have to build a design system. You can work hand-in-hand with a designer and create something consistent with your brand, powerful, and easy to use.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to learn
&lt;/h2&gt;

&lt;p&gt;Ok, so now you're sold on the fact that you need to learn design. What should you learn then? Here is a non-exhaustive list of topics to explore:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Learn a design tool: &lt;a href="https://www.sketch.com/" rel="noopener noreferrer"&gt;Sketch&lt;/a&gt;, &lt;a href="https://www.figma.com/" rel="noopener noreferrer"&gt;Figma&lt;/a&gt; or &lt;a href="https://www.adobe.com/products/xd.html" rel="noopener noreferrer"&gt;Adobe XD&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Whitespace&lt;/li&gt;
&lt;li&gt;Alignment&lt;/li&gt;
&lt;li&gt;Shadows&lt;/li&gt;
&lt;li&gt;Typography&lt;/li&gt;
&lt;li&gt;Colors&lt;/li&gt;
&lt;li&gt;Typography&lt;/li&gt;
&lt;li&gt;Icons&lt;/li&gt;
&lt;li&gt;Base components: buttons, inputs, headers, cards, and more.&lt;/li&gt;
&lt;li&gt;Etc.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>design</category>
      <category>career</category>
    </item>
    <item>
      <title>Task Estimation for Developers</title>
      <dc:creator>Thomas Lombart</dc:creator>
      <pubDate>Mon, 13 Apr 2020 09:04:11 +0000</pubDate>
      <link>https://dev.to/thomaslombart/task-estimation-as-a-front-end-developer-do-it-right-5glc</link>
      <guid>https://dev.to/thomaslombart/task-estimation-as-a-front-end-developer-do-it-right-5glc</guid>
      <description>&lt;p&gt;🙂 &lt;strong&gt;Tuesday 11AM.&lt;/strong&gt; You sit down with your team in a meeting room to plan your next tasks. New features, improvements, and bugs are introduced to you. The product owner (or product manager or engineering manager, whatever!) shows you the mockups and the requirements. You discuss them, and then, for one feature, he asks you the dreaded question:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"Can you estimate how long this task is going to take?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Confidently, because you’re a bad-ass rockstar developer, you answer:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"Hum. Let me think. Yeah, this is not really complex. Two days, not more, not less."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Great, your product owner is happy. We’re going to ship the next sprint. This is huuuuge!&lt;/p&gt;

&lt;p&gt;Once the meeting’s over, you start your task, everything’s going well. After a few hours, you scratch your head. You didn’t pay attention to the endpoint you called. Some data’s missing! You talk with a back-end developer, and you find a solution. That’s a bummer. You wasted a few hours.&lt;/p&gt;

&lt;p&gt;😓 &lt;strong&gt;Wednesday, 10AM&lt;/strong&gt;. during the daily meeting, you say:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"Yesterday, I worked on feature X. I had a problem because some data was missing. I’m nearly done. I’ll finish it today."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In reality, you hope you’ll finish it today because you’ve done half the job and you also have two meetings you can’t escape! But hey, things are going to be alright.&lt;/p&gt;

&lt;p&gt;During the day, you work on the feature, and then you realize something, the mockups we gave you don’t cover the whole thing. What do we show to the user when there’s no data? And what if an error occurs while I’m calling that endpoint? Thus, you gather with the design team, discuss it, and handle new things.&lt;/p&gt;

&lt;p&gt;It’s 6PM. You’re tired, you can’t think. Ok, you’re a little late, but tomorrow you’ll finish the task.&lt;/p&gt;

&lt;p&gt;😥 &lt;strong&gt;Thursday, 10AM&lt;/strong&gt;. Daily meeting time:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"I’m nearly done on feature X. I had to talk to the design team because, in this edge case, we didn’t know what to show to the user. We figured it out, and I’ll finish it today."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;During the day, you work on the feature, and everything’s done! Let’s tackle the tests. You struggle with tests, in particular, mocking a function. The whole team is busy, and you’re on your own for this. After a while, you find a solution. &lt;code&gt;git add&lt;/code&gt; , &lt;code&gt;git commit&lt;/code&gt;, &lt;code&gt;git push&lt;/code&gt;. You wait for the review and fix a bug while waiting.&lt;/p&gt;

&lt;p&gt;😨 &lt;strong&gt;Friday, 10AM&lt;/strong&gt;. Daily meeting. Your product owner asks you if the feature is shipped. He wants to test it as soon as possible because he needs it for a presentation. This feature is critical for the business! You’re embarrassed, but that was not your fault, after all. You answer:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"Yes, sorry. I’m nearly done with it. I wasted a few hours on a test, but it’s in code review. It should be good today. In the meantime, I’ll work on bug Y."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In the morning, one developer reviews your code and finds some quirks. He requires you to change some functions. Furthermore, you didn’t document your feature correctly. And on top of that, you architectured the feature weirdly. He shows you a smart way to do so. This is not going to take long, is it? Let’s get back at work.&lt;/p&gt;

&lt;p&gt;It’s 5PM. It’s been a long week, you’re tired, and you chat with your colleagues. You have some good laughs. You’re done. You’ll finish the feature once and for all on Monday.&lt;/p&gt;

&lt;p&gt;😰 &lt;strong&gt;Monday, 10AM&lt;/strong&gt;. As usual, daily meeting:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"Yeaaaah, so Friday… My code was reviewed, and I had to revamp the feature because I could not use our new functions. Also, I had to do a bit of documentation. I’m going to finish that this morning and let’s ship it this afternoon!"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Empowered by the start of a new week, you are productive and finish that in the morning. You &lt;code&gt;git push&lt;/code&gt; it, your pull request is reviewed, merged, and deployed. You test your feature in staging, and you realize something’s wrong even if everything’s fine locally! You investigate that, and you find the bug at the end of the day. You'll fix it tomorrow.&lt;/p&gt;

&lt;p&gt;😱 &lt;strong&gt;Tuesday, 10AM&lt;/strong&gt;. Daily meeting:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"Yesterday, I thought I was done on feature X. But something was weird on the staging environment. I did some investigations, and I discovered that Y was causing the bug. I’ll write the fix this morning!"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You write the fix on a new branch. &lt;code&gt;git add&lt;/code&gt; , &lt;code&gt;git commit&lt;/code&gt;, &lt;code&gt;git push&lt;/code&gt;. Open PR. Waiting for your review. Review. Merged. Deployed. Fingers crossed, let’s hope everything’s good. You test it in staging and… it works 🎉&lt;/p&gt;

&lt;p&gt;Both relieved and embarrassed, you tell your product owner the feature is shipped. Wow. What should have taken two days actually took one week.&lt;/p&gt;




&lt;p&gt;Did you recognize yourself in this story? If yes, don’t worry, it happened to lots of developers. Don’t blame yourself for this. Instead, focus on what to do to avoid this situation. When it comes to working for someone else, you mainly have to do two things: &lt;em&gt;underpromise and overdeliver.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Indeed, you won’t disappoint anyone by underpromising, and by overdelivering, you will even make them happier. If you think about it, if we ask you to estimate your code, it’s because there are some deadlines to meet, a plan to follow. By doing wrong estimations, you force others to reconsider the plan. However, if your estimations are right, the plan can go on safely even if they seem exaggerated.&lt;/p&gt;

&lt;p&gt;Thus, when you’re asked to estimate a task, consider these elements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;You need all the details required&lt;/strong&gt; to perform the task, and it is clear to you. The endpoints you need to call are ready and functional. The mockups are complete. The acceptance criteria for your tasks are also clear.&lt;/li&gt;
&lt;li&gt;You usually have to do &lt;strong&gt;extra tasks&lt;/strong&gt; such as documentation or testing (even if I think testing shouldn’t be an « extra task » but anyway).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You won’t focus on your task only.&lt;/strong&gt; Aside from your task, you’ll maybe have to do code reviews, to fix a bug in production, to assist to some meetings.&lt;/li&gt;
&lt;li&gt;If you haven’t done the same kind of tasks before, you may have &lt;strong&gt;extra difficulties&lt;/strong&gt; doing it. Maybe you’ll need the help of one of your teammates who’s not always available!&lt;/li&gt;
&lt;li&gt;If there’s &lt;strong&gt;code review&lt;/strong&gt; in your team (which I strongly recommend for enforcing quality code), you may be asked to add extra tests, modify your code or other demands.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Technical problems&lt;/strong&gt; can happen along the way. They can be blocking. It’s worse if these technical problems don’t depend on you!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You may have heard that when you’re being asked to estimate a task, you need to double it. That’s true. If you think of all these elements above, you can &lt;em&gt;easily&lt;/em&gt; double it.&lt;/p&gt;

&lt;p&gt;Yes, your boss/manager/product owner will think it’s exaggerated. Still, they usually don’t know in detail how it works under the hood. The sooner you do your task, the better it is for them to always ask if you can deliver fast.&lt;/p&gt;

&lt;p&gt;To be honest, I don’t really like estimating tasks. There are too many factors to rely on. I do the best I can, and I’ll ship the code when it’s ready. But sometimes (even often) you don’t have the choice. You will need to estimate tasks. Thus, I hope this post will help you to estimate front-end tasks like a pro. 🚀&lt;/p&gt;

</description>
      <category>career</category>
      <category>programming</category>
    </item>
    <item>
      <title>Boost Your Workflow in VS Code with User Snippets</title>
      <dc:creator>Thomas Lombart</dc:creator>
      <pubDate>Mon, 06 Apr 2020 14:16:37 +0000</pubDate>
      <link>https://dev.to/thomaslombart/boost-your-workflow-in-vs-code-with-user-snippets-2mkp</link>
      <guid>https://dev.to/thomaslombart/boost-your-workflow-in-vs-code-with-user-snippets-2mkp</guid>
      <description>&lt;p&gt;Typing every single character of your code can feel cumbersome. How many times did you declare a function? Created an object? Imported a module? Created a for loop? Created a component if you're a React or Vue developer? I don't even know how many times I did it, but I think the numbers would be pretty scary 😱&lt;/p&gt;

&lt;p&gt;Luckily for us, our favorite code editor, VS Code, can provide us user snippets to avoid typing all this code manually. For example, you can download these snippets as package extensions and then, you're able to write code in no time! But what if you find yourself typing a code that no extension provides? What if you have specific conventions or objects you use in your team? Do you have no other choice than to do this chore?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No.&lt;/strong&gt; You can define custom user snippets, and that's an easy task! 😌&lt;/p&gt;

&lt;h3&gt;
  
  
  Create a snippet
&lt;/h3&gt;

&lt;p&gt;To do so, press &lt;code&gt;Ctrl + Shift + P&lt;/code&gt; or &lt;code&gt;Cmd + Shift + P&lt;/code&gt; if you're a macOS user and type &lt;code&gt;user snippets&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft3mhw86vjw0o5qdcifgx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft3mhw86vjw0o5qdcifgx.png" alt="Command palette in VS Code" width="800" height="82"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Select the language for which you're going to create a snippet file. Here we're going to do one for javascript:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5u6evrvavot3c0zu2osp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5u6evrvavot3c0zu2osp.png" alt="Selecting a language for the snippet file" width="800" height="173"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;VS Code should open a new file with some information on how to create a snippet. How nice is this? With this first example, you learn that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A snippet has a name, a prefix, a description and a body. The prefix represents the characters you need to type to trigger the snippet.&lt;/li&gt;
&lt;li&gt;The body is an array, each element defining a line.&lt;/li&gt;
&lt;li&gt;You need to use &lt;code&gt;$0&lt;/code&gt;, &lt;code&gt;$1&lt;/code&gt;, &lt;code&gt;$2&lt;/code&gt; for your different variables (&lt;code&gt;$0&lt;/code&gt; is the final position and &lt;code&gt;$1&lt;/code&gt; and &lt;code&gt;$2&lt;/code&gt; are tab stops).&lt;/li&gt;
&lt;li&gt;If you want to provide a default value for the variables, you can define placeholders: &lt;code&gt;${1:placeholder}&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Console snippet
&lt;/h3&gt;

&lt;p&gt;Let's see a first snippet for logging the content of a variable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;something&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;variable&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, you have two variables: the information you want to log and the variable.&lt;br&gt;
You'll probably want to start a new line after logging. To create such a snippet, go to the &lt;code&gt;javascript.json&lt;/code&gt; file and add the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Print to console"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"prefix"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"csl"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"body"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"console.log('$1', $2);"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"$0"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Logs something to the console"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe9ee6i8fh1u5nnfx4v2c.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe9ee6i8fh1u5nnfx4v2c.gif" alt="GIF showing how to use the console snippet" width="1186" height="162"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here, we defined two lines in &lt;code&gt;body&lt;/code&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The first line (first array element) has two variables: &lt;code&gt;$1&lt;/code&gt; for the information to log and &lt;code&gt;$2&lt;/code&gt; for the variable.&lt;/li&gt;
&lt;li&gt;The second line has just &lt;code&gt;$0&lt;/code&gt; to indicate your final cursor position so that you can go to a new line.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Voilà! You already have a first snippet that works. And that's just the beginning of what you can do with snippets.&lt;/p&gt;

&lt;h3&gt;
  
  
  Try/catch snippet
&lt;/h3&gt;

&lt;p&gt;Let's do another one: writing some code wrapped in a &lt;code&gt;try/catch&lt;/code&gt; statement!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Try catch"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"prefix"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"try"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"body"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"try {"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s2"&gt;$0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"} catch (${1:err}) {"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s2"&gt;$2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"}"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Outputs a try/catch statement"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh74la4txxrtpbazye5e2.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh74la4txxrtpbazye5e2.gif" alt="GIF showing how to use the try snippet" width="1186" height="409"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That one is a little bit trickier to define:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The first line of the body only has the &lt;code&gt;try&lt;/code&gt; statement&lt;/li&gt;
&lt;li&gt;The second line has a tab character (&lt;code&gt;\t&lt;/code&gt;) to add some whitespaces and &lt;code&gt;$0&lt;/code&gt; since this is where you'll finally write your code.&lt;/li&gt;
&lt;li&gt;The third line has the &lt;code&gt;catch&lt;/code&gt; statement: Here, we use placeholders to pre-define the alias of the error variable &lt;code&gt;${1:err}&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The fourth line allows to write the code in the &lt;code&gt;catch&lt;/code&gt; statement&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Improved console snippet
&lt;/h3&gt;

&lt;p&gt;One cool thing you can do is to give multiple choices for a placeholder, the syntax being: &lt;code&gt;${1|one,two,three}&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For example, you can create an improved &lt;code&gt;console&lt;/code&gt; snippet by choosing which method of console (&lt;code&gt;log&lt;/code&gt;, &lt;code&gt;info&lt;/code&gt;, &lt;code&gt;warn&lt;/code&gt;, etc.) you want to call:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Print to console"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"prefix"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"csl"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;highlight-next-line&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"body"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"console.${1|log,info,warn,err|}($2)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"$0"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Logs something to the console"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fujk8nr2lm8yyhrsv5et8.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fujk8nr2lm8yyhrsv5et8.gif" alt="GIF showing how to use the improved console snippet" width="1186" height="408"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Test snippet
&lt;/h3&gt;

&lt;p&gt;From here, you can do a lot of powerful stuff in your editor. Bootstraping files can be much quicker than before!&lt;/p&gt;

&lt;p&gt;For example, I use &lt;a href="https://testing-library.com/docs/react-testing-library/intro" rel="noopener noreferrer"&gt;react-testing-library&lt;/a&gt; for my tests, and I have custom render methods in it. Writing a new test file can be quite long, so I can automate it with a snippet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"New React test file"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"prefix"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"rtl:customRender"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"body"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"import React from &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"import { screen } from &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;@testing-library/react&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"import { ${1|renderWithRouter,renderWithRouterAndProviders|} } from &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;$2&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"import $3 from &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;./$3&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"describe(&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;$3&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;, () =&amp;gt; {"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s2"&gt;test(&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;$4&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;, () =&amp;gt; {"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\t\t&lt;/span&gt;&lt;span class="s2"&gt;$1(&amp;lt;$3/&amp;gt;)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\t\t&lt;/span&gt;&lt;span class="s2"&gt;$0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s2"&gt;})"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"})"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Creates a new React test file with custom render"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;By using the variable &lt;code&gt;$3&lt;/code&gt; multiple times, I can write once at different places in the code. It's really handy for the component name.&lt;/li&gt;
&lt;li&gt;I am also able to choose which render method to use from a test utils file&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By defining all kinds of snippets, you can definitely &lt;strong&gt;improve your workflow and save time!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you're working in a team of many developers, it's a great idea to &lt;strong&gt;share these snippets&lt;/strong&gt; across your team. In VS Code, you can do so by including these snippets in a &lt;code&gt;.vscode&lt;/code&gt; folder with a &lt;code&gt;.code-snippets&lt;/code&gt; extension! 😎&lt;/p&gt;

</description>
      <category>vscode</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Object and Array Destructuring in JavaScript</title>
      <dc:creator>Thomas Lombart</dc:creator>
      <pubDate>Mon, 30 Mar 2020 06:05:29 +0000</pubDate>
      <link>https://dev.to/thomaslombart/object-and-array-destructuring-in-javascript-eg9</link>
      <guid>https://dev.to/thomaslombart/object-and-array-destructuring-in-javascript-eg9</guid>
      <description>&lt;p&gt;When ES2015 (also known as ES6) got released, powerful new features saw the day like the &lt;strong&gt;destructuring assignment syntax.&lt;/strong&gt; In short, it allows us to unpack values from arrays or properties from objects quickly and straightforwardly.&lt;/p&gt;

&lt;p&gt;Consider this post as a quick reference when you want to check out something on destructuring in JavaScript. ☺️&lt;/p&gt;

&lt;p&gt;Let's say you have a &lt;code&gt;user&lt;/code&gt; object with different properties like the &lt;code&gt;name&lt;/code&gt;, the &lt;code&gt;age&lt;/code&gt;, the &lt;code&gt;email&lt;/code&gt; address. You want to assign variables to these different properties, here is how to do it with and without destructuring:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// The old way: a bit verbose&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;age&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Using destructuring&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;age&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Short and clear: that's the power of destructuring.&lt;/p&gt;

&lt;p&gt;Now, let's say your user also has an &lt;code&gt;address&lt;/code&gt; property, itself composed of a &lt;code&gt;street&lt;/code&gt;, &lt;code&gt;city&lt;/code&gt;, &lt;code&gt;country&lt;/code&gt;, and &lt;code&gt;postal_code&lt;/code&gt; properties. You can also use &lt;code&gt;destructuring&lt;/code&gt; to handle &lt;strong&gt;nested objects&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Assign the name, email, city and country&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;city&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;country&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But what if you would like to assign the &lt;code&gt;city&lt;/code&gt; and &lt;code&gt;country&lt;/code&gt; variables while keeping the whole &lt;code&gt;address&lt;/code&gt; object? That's still possible:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Destructure city, country and keep the address object as-is&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;city&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;country&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sometimes when you retrieve data from an API, the variable names can be quite different. Imagine that the &lt;code&gt;user&lt;/code&gt; object has an &lt;code&gt;user_id&lt;/code&gt; property, and you want to rename it just &lt;code&gt;id&lt;/code&gt;. It's useful in these cases to &lt;strong&gt;rename variables&lt;/strong&gt; while destructuring using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Destructure user_id and rename it to id&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The power of destructuring doesn't stop here. You can assign &lt;strong&gt;default values&lt;/strong&gt; to properties in case they're not defined. For example, if your user were to have a favorite &lt;code&gt;theme&lt;/code&gt; (&lt;code&gt;light&lt;/code&gt; or &lt;code&gt;dark&lt;/code&gt;) property, you could default it to light mode:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// If `theme` isn't defined, use the light mode by default&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;theme&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;light&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that everything said above also works for &lt;strong&gt;function arguments&lt;/strong&gt;. For example, you could imagine a &lt;code&gt;displayAddress&lt;/code&gt; function taking a &lt;code&gt;user&lt;/code&gt; object argument:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Destructure the user object and set the country to France by default&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;displayAddress&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;city&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;country&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;France&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Note the use of template literals, another ES2015 feature&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; lives in &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;city&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;, &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;country&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you're using React, it can also be useful when creating &lt;strong&gt;functional components&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;age&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;, &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;age&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; years old
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that it's also possible to destructure some properties of an object and still save the rest of the properties using the &lt;strong&gt;rest parameter&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Assign the name and the email of the user and store the other properties in userInfos&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;userInfos&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It can also be handy in React if you need some props and need to pass down the other props.&lt;br&gt;
Here's an example applied to routing in React:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;PrivateRoute&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FC&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Props&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;rest&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Get the user's authentication status&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;isAuthenticated&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useAuth&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Route&lt;/span&gt;
      &lt;span class="c1"&gt;// Pass all the props to Route except `component`&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;rest&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="na"&gt;render&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class="c1"&gt;// if the user is authenticated, render the component otherwise redirect him to the signin screen&lt;/span&gt;
        &lt;span class="nx"&gt;isAuthenticated&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Component&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Redirect&lt;/span&gt; &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/signin"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// Can be used that way:&lt;/span&gt;
&lt;span class="c1"&gt;// &amp;lt;PrivateRoute path="/create" component={CreatePost} /&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Wait, wait, wait. The next one is even cooler. You can make use of &lt;strong&gt;dynamic&lt;/strong&gt; destructuring by using computed property keys. Imagine that you have a &lt;code&gt;users&lt;/code&gt; object and you want to normalize it by user ID (meaning that the key is the user ID). You can do that with destructuring:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;afb4d&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Mike&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;27&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fea4i&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Emma&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;38&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;normalizedUsers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;usersById&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Assign the user object to its ID...&lt;/span&gt;
    &lt;span class="c1"&gt;// highlight-next-line&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;// ... and return the whole normalized users object&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;usersById&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{});&lt;/span&gt;

&lt;span class="cm"&gt;/* 
normalizedUsers is now
{
  afb4d: { id: 'afb4d', name: 'Mike', age: 27 },
  fea4i: { id: 'fea4i', name: 'Emma', age: 38 }
}
*/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Destructuring also works for &lt;strong&gt;arrays&lt;/strong&gt;. Let's say you retrieve a list of users (let's call it &lt;code&gt;mostActiveUsers&lt;/code&gt;) sorted by the number of comments a user posted. You only want to display the first three users:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Retrieve the first three most active users&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;first&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;second&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;third&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mostActiveUsers&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What if you'd like to get only the fourth user from this list? Well, it's also possible to &lt;strong&gt;skip items&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Skip the first three most active users&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[,&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fourth&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mostActiveUsers&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You could also get the first three most active users and still store the other users with the &lt;strong&gt;rest parameter&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;first&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;second&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;third&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;otherUsers&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mostActiveUsers&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's recap. You saw how to destructure objects (with nested objects), rename variables, assign default values, how destructuring applies to function arguments (and thus to components in React). You also saw dynamic destructuring, destructuring arrays, skipping array items and how to use the rest parameter with both objects and arrays.&lt;br&gt;
You're now ready to unlock the full potential of destructuring in your app! 😎&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
