Dealing with Government of Canada logos on the web

Despite the Government of Canada having a web presence for 30 years now, one of the weirdly persistent problems when building government web applications is how to deal with logos.

The problem is with what is known as “signature blocks”; the combination of flag plus department name (or just “Government of Canada”) that you’ll find at the top of every website.

At first glance, it’s a solved problem, but if you look closely at one of these largely textual logos you’ll notice that it’s a picture: The logos all include an image of text rather than text itself, along with a flag.

This is visible everywhere from the new Design System, to Canada.ca itself, all recycling the same problematic logos.

Given that this is a well known accessibility problem, and doesn’t respect my choice of language (on the web I can specify my language, but the logo images always include both), and doesn’t work for mobile devices (including both languages isn’t good on a small screen)… it’s an odd pattern to see across every government site.

Why would anyone make a picture of text?

Because in 1970, the Federal Identity Program selected Helvetica as the official font of the Government of Canada. An eminently reasonable decision for the centralized team and world of print that existed at the time, this has caused major problems for generations of departmental web developers who then realize that as a commercial font Helvetica can’t legally be used without a license. Given the governments broken procurement process, and the insanity of trying to navigate it for each web application people have opted to simply take a picture of the text instead.

This decision, combined with the fact that the only examples of logos all have both languages because of the FIPs origins in signage and stationary (where users can’t express which language they want to see) have created the bizarre mess we have currently.

Helvetica compatible fonts to the rescue

There have been a few “Helvetica clones” published over the years that allow us to do something reasonable for the web without messing with existing signage.

For our goal of visual compatibility with existing signage, one of the selection criteria is whether they preserve Helvetica’s distinctive “spur” on the capital G, something the words “Government of Canada” will make immediately noticeable. Overused Grotesk does this, and also stands out for having a web-friendly variable font version.

With font in hand, we can solve these accessibility and screen real-estate problems by using a proper font with Government branding.

To show how this can work, here is copy-paste friendly example of setting up Overused Grotesk in a new project so that it’s properly preloaded so that the page loads without the infamous Flash of Unstyled Text (FOUT).

Let’s use Rsbuild to scaffold a basic React application for us.

$ npm create rsbuild@latest

> npx
> create-rsbuild

◆  Create Rsbuild Project
│
◇ Project name or path
│  fontpreload
│
◇ Select framework
│  React 19
│
◇ Select language
│  TypeScript
│
◇ Select additional tools (Use <space> to select, <enter> to continue)
│  Add Biome for code linting and formatting
│
◇ Next steps ─────────────╮
│                          │
│  1. cd fontpreload       │
│  2. git init (optional)  │
│  3. npm install          │
│  4. npm run dev          │
│                          │
├──────────────────────────╯
│
└  All set, happy coding!

In this application we’ll need a copy of that Overused Grotesk font. We can use curl to both download the font put it in static/font which works nicely with Rsbuilds defaults.

curl 'https://raw.githubusercontent.com/RandomMaerks/Overused-Grotesk/refs/heads/main/fonts/variable/OverusedGrotesk-VF.woff2' --create-dirs --output-dir static/font --output OverusedGrotesk-VF.woff2

Rsbuild’s default template doesn’t include a lang attribute on the <html> element, or a <meta> description, so we’ll add a minimalist template in the static folder too.

cat << EOF > static/index.html
<!doctype html>
<html lang="en">
  <head>
    <meta name="description" content="Rsbuild application" />
  </head>
  <body>
    <div id="<%= mountId %>"></div>
  </body>
</html>
EOF

Now we’ll add some basic config for Rsbuild, telling it to use our template, skip bundling licence files, and most importantly to preload our font and other assets which is the key to avoid the Flash of Unstyled Text (FOUT).

patch rsbuild.config.ts <<'EOF'
diff --git a/rsbuild.config.ts b/rsbuild.config.ts
index c55b3e1..799d5ae 100644
--- a/rsbuild.config.ts
+++ b/rsbuild.config.ts
@@ -4,4 +4,29 @@ import { pluginReact } from '@rsbuild/plugin-react';
 // Docs: https://rsbuild.rs/config/
 export default defineConfig({
   plugins: [pluginReact()],
+  html: {
+    // use a custom template to address A11y and SEO issues.
+    template: "./static/index.html",
+    tags: [
+      {
+        tag: 'link',
+        attrs: {
+          rel: 'preload',
+          type: 'font/woff2',
+          as: 'font',
+          href: '/static/font/OverusedGrotesk-VF.woff2',
+          crossorigin: 'anonymous',
+        },
+      },
+    ],
+  },
+  output: {
+    // This will prevent .LICENSE.txt files from being generated
+    legalComments: "none",
+    filename: {
+      // Don't use a hash in the font filename, so our tags above can
+      // reference the font files directly.
+      font: "[name][ext]",
+    },
+  },
 });
EOF

Now we include an @font-face rule specifying where we want to load our font from. Rsbuild will run rspack on this file which will normally rewrite the src to point to the bundled file (something like src: url(/static/font/OverusedGrotesk-VF.1656e9bd.woff2)format("woff2");). Including filename.font: "[name][ext]", ensures that it doesn’t add that hash, so the name lines up with the name in our href in the tags section.

patch src/App.css << 'EOF'
 diff --git a/src/App.css b/src/App.css
index 164c0a6..ae9754b 100644
--- a/src/App.css
+++ b/src/App.css
@@ -1,7 +1,15 @@
+@font-face {
+  font-family: "Overused Grotesk";
+  src: url("../static/font/OverusedGrotesk-VF.woff2") format("woff2");
+  font-weight: 300 900;
+  font-style: normal;
+  font-display: fallback;
+}
+
 body {
   margin: 0;
   color: #fff;
-  font-family: Inter, Avenir, Helvetica, Arial, sans-serif;
+  font-family: "Overused Grotesk", Inter, Avenir, Helvetica, Arial, sans-serif;
   background-image: linear-gradient(to bottom, #020917, #101725);
 }
EOF

Now we can add a little text with a capital G, so that it’s easy to see that our font is loaded and used.

patch src/App.tsx << 'EOF'
diff --git a/src/App.tsx b/src/App.tsx
index dff1751..cebdc5b 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -3,7 +3,7 @@ import './App.css';
 const App = () => {
   return (
     <div className="content">
-      <h1>Rsbuild with React</h1>
+      <h1>Rsbuild with Overused Grotesk</h1>
       <p>Start building amazing things with Rsbuild.</p>
     </div>
   );
EOF

And now it’s time to build our production bundle.

$ npm run build

> [email protected] build
> rsbuild build

  Rsbuild v1.4.8

info    build started...
ready   built in 0.13 s

File (web)                                           Size       Gzip
dist/static/css/index.062da953.css                   0.53 kB    0.34 kB
dist/index.html                                      0.63 kB    0.35 kB
dist/static/js/index.58333bd8.js                     1.3 kB     0.78 kB
dist/static/font/OverusedGrotesk-VF.1656e9bd.woff2   85.1 kB
dist/static/js/lib-react.a4a8b05c.js                 182.8 kB   57.9 kB

                                            Total:   270.4 kB   144.4 kB

To get a sense of what this will look like in production, use npm run preview to get Rsbuild to serve us the production build files it just created in the dist folder. The Lighthouse scores are telling us we did this right.

This is pretty good so far. We have a font, and we’re loading it in a way that is good for web performance, but we haven’t really solved the larger problem with logos until we take one final step and make a signature block that uses it.

First, we’ll need to create a React component representing the Canadian flag. You might notice this component is created as a headless component, so that it’s easy to add ARIA attributes (important for accessibility) to and plays nicely with whatever approach you’re using for CSS (something like PandaCSS or Tailwind)

cat << EOF > src/Signature.tsx
import React from "react";

export function SVG({ children, ...props }: React.ComponentProps<"svg">) {
  return (
    <svg
      xmlns="http://www.w3.org/2000/svg"
      preserveAspectRatio="xMinYMin"
      role="img"
      width="65.669"
      height="31.116"
      {...props}
    >
      {children}
    </svg>
  );
}

export function Flag(props: React.ComponentProps<"path">) {
  return (
    <path
      {...props}
      d="m30.675 6.467 2.223-4.443 2.206 4.281c.275.452.499.415.938.2l1.898-.921-1.234 5.977c-.258 1.174.422 1.518 1.162.722l2.705-2.837.718 1.605c.241.485.605.415 1.086.328l2.794-.577-.938 3.464v.074c-.11.453-.33.83.186 1.05l.993.485-5.782 4.783c-.587.593-.384.776-.164 1.444l.532 1.605-5.372-.954c-.663-.162-1.124-.162-1.14.361l.219 6.048h-1.614l.22-6.031c0-.594-.461-.577-1.547-.357l-4.983.937.642-1.605c.22-.614.279-1.029-.22-1.444l-5.87-4.716 1.086-.651c.313-.237.33-.486.165-1.013l-1.104-3.505 2.831.593c.79.183 1.01 0 1.213-.414l.79-1.59 2.799 3.07c.494.577 1.196.2.976-.63l-1.344-6.48 2.08 1.174c.329.2.68.253.883-.124M50.099 0h15.57v31.116h-15.57ZM0 0h15.57v31.116H0Z"
    />
  );
}
EOF

And finally we’ll import that into our App component to create a our new signature block. Notice how we can add styles and ARIA attributes as needed, without worrying about a customizability wall.

patch src/App.tsx << 'EOF'
diff --git a/src/App.tsx b/src/App.tsx
index cebdc5b..f9f58f9 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -1,9 +1,26 @@
 import './App.css';
+import { Flag, SVG } from "./Signature.tsx";

 const App = () => {
   return (
-    <div className="content">
-      <h1>Rsbuild with Overused Grotesk</h1>
+    <div className="content" style={{ justifySelf: "center" }}>
+      <section
+        style={{ display: "flex" }}
+      >
+        <SVG>
+          <title>Canadian Flag</title>
+          <Flag style={{ fill: "#ea2d37" }} />
+        </SVG>
+        <span
+          style={{
+            paddingLeft: "0.8em",
+            lineHeight: "1em",
+            textAlignLast: "left",
+          }}
+        >
+          Government of<br /> Canada
+        </span>
+      </section>
       <p>Start building amazing things with Rsbuild.</p>
     </div>
   );
EOF

The result is super satisfying, a razor-sharp and accessible signature block looks great at any zoom level and on any screen size. It’s easily styled, and works really well with internationalization libraries like the one I covered in a previous post.

Using an Open Source font to maintain visual compatibility with FIP feels like win-win: Nobody needs to change physical signage/letterhead, lingering accessibility problems can be solved and the user experience for every government web site improves a little… all for a cost of $0.

i18n for Rsbuild with Lingui

With the sunsetting of Create React App, I’ve wanted to find something similar but with a more minimalistic vibe.

Two projects that caught my eye are the Rust-based rewrite of Webpack called Rspack, and it’s Create React App equivalent companion project Rsbuild. Of course here in Canada I’m going to want that along with proper internationalization (i18n) using my favourite library Lingui.

With Rsbuild creating a minimalistic Single Page Application pre-configured with the Rspack bundler, and both Lingui and Rspack working with the rust-based transpiler SWC (a faster equivalent of Babel) these actually work together nicely and are my new favorite way to start a project.

What follows is a cut-and-paste friendly walk-though to get translations working.

We’ll use the command npm create rsbuild@latest to create our project skeleton.

$ npm create rsbuild@latest

> npx
> create-rsbuild


◆  Create Rsbuild Project
│
◇  Project name or path
│  lingui-demo
│
◇  Select framework
│  React 19
│
◇  Select language
│  JavaScript
│
◇  Select additional tools (Use <space> to select, <enter> to continue)
│  Add Biome for code linting and formatting
│
◇  Next steps ─────────────╮
│                          │
│  1. cd lingui-demo       │
│  2. git init (optional)  │
│  3. npm install          │
│  4. npm run dev          │
│                          │
├──────────────────────────╯
│
└  All set, happy coding!

Using fd the modern (and git aware) equivalent of find we can see that the structure of this project is nice and simple: 2 JS files and a bit of CSS along with 3 config files and a readme.

$ git init && echo node_modules >> .gitignore
Initialized empty Git repository in /home/mike/projects/lingui-demo/.git/
$ fd
README.md
biome.json
package.json
public/
rsbuild.config.mjs
src/
src/App.css
src/App.jsx
src/index.jsx

The first step is to install the dependencies for Lingui.

npm install @lingui/core @lingui/react
npm install --save-dev @lingui/swc-plugin @lingui/cli

Next we’ll add a config file for Lingui specifying the locales we want and where they should be stored.

cat << EOF > lingui.config.js
import { defineConfig } from '@lingui/cli';

export default defineConfig({
  sourceLocale: 'en',
  locales: ['fr', 'en'],
  catalogs: [
    {
      path: '<rootDir>/src/locales/{locale}/messages',
      include: ['src'],
    },
  ],
});
EOF

And now we’ll connect the dots by adding some SWC config to our rsbuild.config.mjs file. The idea is that rsbuild will pass this through to rspack, so that its built-in swc-loader is properly configured with Lingui’s @lingui/swc-plugin

patch rsbuild.config.mjs <<'EOF'
diff --git a/rsbuild.config.mjs b/rsbuild.config.mjs
index c9962d3..70154c3 100644
--- a/rsbuild.config.mjs
+++ b/rsbuild.config.mjs
@@ -3,4 +3,13 @@ import { pluginReact } from '@rsbuild/plugin-react';

 export default defineConfig({
   plugins: [pluginReact()],
+  tools: {
+    swc: {
+      jsc: {
+        experimental: {
+          plugins: [['@lingui/swc-plugin', {}]],
+        },
+      },
+    },
+  },
 });
EOF

I’ll use jq to add scripts for lingui’s extract and compile commands (documentation) to the scripts section of our package.json file.

jq '.scripts += {"extract": "lingui extract", "compile": "lingui compile"}' package.json | sponge package.json

Now we need two things that don’t exist yet: a function to dynamically load the locales (borrowing heavily from the one in their documentation) and some buttons that would let us switch languages.

First up, that dynamic loading function.

cat <<'EOF' > src/i18n.js
import { i18n } from '@lingui/core';

export const defaultLocale = 'en';

export async function dynamicActivate(locale) {
  const { messages } = await import(`./locales/${locale}/messages`);
  i18n.load(locale, messages);
  i18n.activate(locale);
  return i18n;
}
EOF

And then our fancy buttons.

cat <<'EOF' > src/LocaleSwitcher.jsx
import React from 'react';
import { locales, dynamicActivate } from './i18n.js';

function LocaleSwitcher() {
  return (
    <div>
      <button type="button" onClick={async () => dynamicActivate('en')}>
        English
      </button>
      <button type="button" onClick={async () => dynamicActivate('fr')}>
        Français
      </button>
    </div>
  );
}

export default LocaleSwitcher;
EOF

Now we’ll use that dynamicActivate function to help set up Lingui’s I18nProvider

patch src/index.jsx <<'EOF'
diff --git a/src/index.jsx b/src/index.jsx
index 65a8dbf..c919c24 100644
--- a/src/index.jsx
+++ b/src/index.jsx
@@ -1,10 +1,16 @@
 import React from 'react';
 import ReactDOM from 'react-dom/client';
 import App from './App';
+import { I18nProvider } from '@lingui/react';
+import { dynamicActivate, defaultLocale } from './i18n';
+
+const i18n = await dynamicActivate(defaultLocale);

 const root = ReactDOM.createRoot(document.getElementById('root'));
 root.render(
   <React.StrictMode>
-    <App />
+    <I18nProvider i18n={i18n}>
+      <App />
+    </I18nProvider>
   </React.StrictMode>,
 );
EOF

We’ll mark the default text in the src/App.jsx for translation and pull in that <LocaleSwitcher/> component so we can see this thing working.

patch src/App.jsx <<'EOF'
diff --git a/src/App.jsx b/src/App.jsx
index dff1751..629fab9 100644
--- a/src/App.jsx
+++ b/src/App.jsx
@@ -1,10 +1,18 @@
+import React from 'react';
+import { Trans } from '@lingui/react/macro';
+import LocaleSwitcher from './LocaleSwitcher.jsx';
 import './App.css';

 const App = () => {
   return (
     <div className="content">
-      <h1>Rsbuild with React</h1>
-      <p>Start building amazing things with Rsbuild.</p>
+      <LocaleSwitcher />
+      <h1>
+        <Trans>Rsbuild with React</Trans>
+      </h1>
+      <p>
+        <Trans>Start building amazing things with Rsbuild.</Trans>
+      </p>
     </div>
   );
 };
EOF

With the setup out of the way, we’ll use the lingui extract command to comb through our code for translatable strings and write them into the translation files. Notice it even tells us that we’re missing some translations!

$ npm run extract

> [email protected] extract
> lingui extract

✔
Catalog statistics for src/locales/{locale}/messages:
┌─────────────┬─────────────┬─────────┐
│ Language    │ Total count │ Missing │
├─────────────┼─────────────┼─────────┤
│ fr          │      2      │    2    │
│ en (source) │      2      │    -    │
└─────────────┴─────────────┴─────────┘

That extract command will extract all the strings marked as translatable with the <Trans> component into the .po files in the locales directory. Then we’ll update the non-default translation file in src/locales/fr/messages.po with the translated text.

patch src/locales/fr/messages.po <<'EOF'
diff --git a/src/locales/fr/messages.po b/src/locales/fr/messages.po
index 0c52442..f7dabe8 100644
--- a/src/locales/fr/messages.po
+++ b/src/locales/fr/messages.po
@@ -15,8 +15,8 @@ msgstr ""

 #: src/App.jsx:11
 msgid "Rsbuild with React"
-msgstr ""
+msgstr "Rsbuild avec React"

 #: src/App.jsx:14
 msgid "Start building amazing things with Rsbuild."
-msgstr ""
+msgstr "Commencez à créer des choses incroyables avec Rsbuild."
EOF

Don’t forget to run npm run compile to get those strings ready for use in your app. After that, run npm run dev to admire your freshly internationalized application!

Tagged template literals and the hack that will never go away

Tagged template literals were added to the JavaScript as part of the 2015 update to the ECMAScript standard.

While a fair bit has been written about them, I’m going to argue their significance is underappreciated and I’m hoping this post will help change that. In part, it’s significant because it solves a problem people had resigned themselves to living with: SQL injection.

Before ES 2015, combining query strings with variables was done via concatenation using the plus operator.

It’s common to retrieve things from the database with information (like an product id) supplied by users, so code like this was common and resulted in many security vulnerabilities.

let query = "select * from widgets where id = " + 1 + ";"

As of ES 2015, you can now write this differently, by creating multi-line strings using backticks, and use ${} for variable interpolation within them.

let query = `select * from widgets where id = ${1};`

This is a lot nicer (less “noise”) but still problematic security-wise. It’s pairing this new syntax with another language feature known as tagged templates that give us the tools to solve sql injections once and for all:

let id = 1
// define a function to use as a "tag"
sql = (strings, ...vars) => ({strings, vars})
[Function: sql]
// call our "tag" function with a template literal
sql`select * from widgets where id = ${id};`
{ strings: [ 'select * from widgets where id = ', ';' ], vars: [ 1 ] }

What you see above is still just a function call, but it no longer works the same. Instead of doing the variable interpolation first and then calling the sql function with the resulting string (select * from widgets where id = 1;), the sql function is passed an array of string segments and the variables that are supposed to be interpolated.

You can see how different this is from the standard evaluation process by adding brackets to make this a standard function invocation; it switches back to the standard function invocation… the string is once again interpolated before being passed to the sql function, entirely losing the distinction between the value (which we probably don’t trust) and the string (that we probably do). The result is an injected string and an empty array of variables.

sql(`select * from widgets where id = ${id};`)
{ strings: 'select * from widgets where id = 1;', vars: [] }

This loss of context (the distinction between the variables/values and the query itself) is the heart of matter when it comes to SQL injection (or injection attacks generally). The moment the strings and variables are combined you have a problem on your hands.

So why not just use parameterized queries or something similar? It’s generally held that good code expresses the programmers intent. I would argue that select * from widgets where id = ${id}; perfectly expresses the programmers intent; the programmer wants the id variable to be included in the query string.

When the clearest expression of a programmers intent is also a security problem what you have is a systemic issue which requires a systemic fix.

This is why despite years of condescending security training, developer shaming and “push left” pep-talks SQL injection stubbornly remains “the hack that will never go away”. Pointing out the problem is easy, but providing implementable solutions is hard (especially since most security people don’t write code). As others have pointed out:

First, we need to deal with the standing advice of “Don’t trust your input.” This advice doesn’t give the programmers any actionable solution: what to trust, and how to build trust?

Given how ineffective the security industry has been so far, it’s fascinating to see Mike Samuel from Google’s security team as the champion of the “Template Strings” proposal. Even more telling is the mantra from his GitHub profile: “make the easiest way to express an idea in code a secure way to express that idea”.

You can see the fruits of his labour by noticing library authors leveraging this to deliver a great developer experience while doing the right thing for security. Allan Plum, the driving force behind the Arangodb Javascript driver leveraging tagged template literals to let users query ArangoDB safely.

The aql (Arango Query Language) function lets you write what would in any other language be an intent revealing SQL injection, safely returns an object with a query and some accompanying bindvars.

aql`FOR thing IN collection FILTER thing.foo == ${foo} RETURN thing`
{ query: 'FOR thing IN collection FILTER thing.foo == @value0 RETURN thing',
  bindVars: { value0: 'bar' } }

Mike Samuel himself has a number of node libraries that leverage Tagged Template Literals, among them one to safely handle shell commands.

sh`echo -- ${a} "${b}" 'c: ${c}'`

It’s important to point out that Tagged Template Literals don’t entirely solve SQL injections, since there are no guarantees that any particular tag function will do “the right thing” security-wise, but the arguments the tag function receives set library authors up for success.

Authors using them get to offer an intuitive developer experience rather than the clunkiness of prepared statements, even though the tag function may well be using them under the hood. The best experience is from safest thing; It’s a great example of creating a “pit of success” for people to fall into.

// Good security hinges on devs learning to write clunky
// stuff like this instead of the simple stuff above.
const ps = new sql.PreparedStatement(/* [pool] */)
ps.input('param', sql.Int)
ps.prepare('select * from widgets where id = @id;', err => {
    // ... error checks
    ps.execute({id: 1}, (err, result) => {
        // ... error checks
        ps.unprepare(err => {
            // ... error checks
        })
    })
})

It’s an interesting thought that JavaScripts deficiencies seem to have become it’s strength. First Ryan Dahl filled out the missing IO pieces to create Node JS and now missing features like multi-line string support provide an opportunity for some of the worlds most brilliant minds to insert cutting edge security features along-side these much needed fixes.

I’m really happy to finally see language level fixes for things that are clearly language level problems takes JavaScript next. It’s the only way I can see to move the needle in the security space and make perennial problems like “the hack that will never go away” finally go away.

Javascript i18n with Lingui

Living in a country with two official lanaguage means that you don’t get far into a project before the question of internationalization (aka i18n to anyone who has to type it more than a few times) comes up.

There are a few options for dealing with this in Javascript, but it’s taken a while to find one I like. First, I expect to use the same library on the server and on the client, and I expect to be able to use it with libraries like React.

React-Intl works OK on the client side, but using the underlying Intl on the server looks under-documented and deeply clunky. I18next is reasonable on the server and has integrations with most client side frameworks. While it’s a decent choice, there is something about the way it works which rubs me the wrong way.

i18next.init({
  lng: 'en',
  fallbackLng: 'en',
  resources: {
    en: {
      translation: {
        person: {
          firstName: "First name",
          lastName: "Last name",
	}
      },
    },
    fr: {
      translation: {
        person: {
          firstName: "Prénom",
          lastName: "Nom de famille",
	}
      },
    },
  }
})

The above code shows how to use it. It’s a pretty standard setup (very familiar if you’ve ever done i18n in Rails), some singleton object (you can make others if you need to) with an internal collection of messages which are stored as a JSON object.

One of the things that I dislike about this approach is that the translations stored in that JSON object tend to accumulate and hang around long after the code that needs that message is gone.

The other thing I find doesn’t sit well with me is the way you access those messages: i18n.t('mutation.fields.purchase.args.expiryYear').

What you are looking at is a function call that assumes the existence of an object like {translation:{fields:{purchase:{args:{expiryYear: "Expiry year"}}}}}. This an example of structural coupling, my code depends on the structure of that object. This sort of thing is normally considered an anti-pattern, a violation of the “law of Demeter”, but it’s pretty common among i18n libraries. I have to decide on the structure to start with, and after that, changing that structure (say if you decide you didn’t make the right decision about how to structure it originally) is going to break a lot of things.

Poking around I stumbled on a library that takes a different approach: Lingui.

Lingui is interesting because it builds a nice translation workflow by leveraging the now ubiquitous infrastructure of Babel.

Aside from the core code in lingui-i18n (and other packages dealing with React) the heart of lingui’s approach are two babel plugins: babel-plugin-lingui-extract-messages and babel-plugin-lingui-transform-js.

We can install what we need for the server side like this.

yarn add lingui-cli lingui-i18n

The babel-plugin-lingui-extract-messages plugin does what is advertised on the tin. First we need a little test code to extract.

const { i18n } = require('lingui-i18n')

i18n.t`I do like a bit of gorgonzola.`
i18n.t`Not even Wensleydale?`

Then we need to create some locales using the helper supplied by lingui-cli:

[mike@longshot lingui]$ lingui add-locale en fr
Added locale en.
Added locale fr.

(use "lingui extract" to extract messages)
[mike@longshot lingui]$ tree
.
├── index.js
├── locale
│   ├── en
│   │   └── messages.json
│   └── fr
│       └── messages.json
├── package.json
└── yarn.lock

Next we use babel-plugin-lingui-extract-messages via the Lingui CLI commandlingui extract to scan our code for those internationalized strings and extract them into translation files.

[mike@longshot lingui]$ lingui extract
Extracting messages from source files…
Collecting all messages…
Writing message catalogues…
Messages extracted!

Catalog statistics:
┌──────────┬─────────────┬─────────┐
│ Language │ Total count │ Missing │
├──────────┼─────────────┼─────────┤
│ en       │      2      │    2    │
│ fr       │      2      │    2    │
└──────────┴─────────────┴─────────┘

(use "lingui add-locale <language>" to add more locales)
(use "lingui extract" to update catalogs with new messages)
(use "lingui compile" to compile catalogs for production)

Lingui prints out a nice summary of the state of my translations.
A look at the translation files shows how Lingui can solve that coupling problem; it generates an object with the content of the strings used as the keys. This way my translations are looked up by content, rather than via their location in some stucture. Since Lingui defaults to showing the message id (which is actually the English content string from the source) we’ll just edit the French messages file.

[mike@longshot lingui]$ cat locale/fr/messages.json 
{
  "I do like a bit of gorgonzola.": {
    "translation": "Je aime un peu de gorgonzola.",
    "origin": [
      [
        "index.js",
        3
      ]
    ]
  },
  "Not even Wensleydale?": {
    "translation": "Pas même Wensleydale?",
    "origin": [
      [
        "index.js",
        4
      ]
    ]
  }
}

With that done we need to compile the json into JS files for use with lingui compile. The missing piece now is the how those i18n.t tagged template literals are going to produce our translated strings at runtime, and the answer is babel-plugin-lingui-transform-js.

Since a picture is worth a thousand words, I think the best way to explain it is this:

[mike@longshot lingui]$ cat index.js | babel --plugins lingui-transform-js
const { i18n } = require('lingui-i18n');

i18n._('I do like a bit of gorgonzola.');
i18n._('Not even Wensleydale?');

As you can see, all the calls to i18n.t`` are replaced with calls to i18n._(). This is underscore function is the low level api that Lingui uses to actually give you the translated strings.

Now that we know that, let’s take a look at what using the library looks like.

[mike@longshot lingui]$ node
> var { i18n, unpackCatalog } = require('lingui-i18n')
undefined
> i18n.load({fr: unpackCatalog(require('./locale/fr/messages.js')), en: unpackCatalog(require('./locale/en/messages.js'))})
undefined
> i18n.availableLanguages
[ 'fr', 'en' ]>
> i18n.activate('en')
undefined
> i18n._('I do like a bit of gorgonzola.')
'I do like a bit of gorgonzola.'
> i18n.activate('fr')
undefined
> i18n._('I do like a bit of gorgonzola.')
'Je aime un peu de gorgonzola.'

Lingui has some more tricks up it’s sleeve like pluralization, but one of the things I’m happiest about is that this approach also solves that “unused messages” problem that I mentioned.

If we delete our “Not even Wensleydale?” message and run lingui extract again we can see the benefits of this static analysis style approach: Lingui knows when there is nothing referencing a message, and marks it as obsolete.

[mike@longshot lingui]$ cat locale/fr/messages.json 
{
  "I do like a bit of gorgonzola.": {
    "translation": "Je aime un peu de gorgonzola.",
    "origin": [
      [
        "index.js",
        3
      ]
    ]
  },
  "Not even Wensleydale?": {
    "translation": "Pas même Wensleydale?",
    "origin": [
      [
        "index.js",
        4
      ]
    ],
    "obsolete": true
  }
}

Better still, Lingui will clean out the obsolete messages for you with lingui extract --clean.

[mike@longshot lingui]$ lingui extract --clean
Extracting messages from source files…
Collecting all messages…
Writing message catalogues…
Messages extracted!

Catalog statistics:
┌──────────┬─────────────┬─────────┐
│ Language │ Total count │ Missing │
├──────────┼─────────────┼─────────┤
│ en       │      1      │    1    │
│ fr       │      1      │    0    │
└──────────┴─────────────┴─────────┘

(use "lingui add-locale <language>" to add more locales)
(use "lingui extract" to update catalogs with new messages)
(use "lingui compile" to compile catalogs for production)
[mike@longshot lingui]$ cat locale/fr/messages.json 
{
  "I do like a bit of gorgonzola.": {
    "translation": "Je aime un peu de gorgonzola.",
    "origin": [
      [
        "index.js",
        3
      ]
    ]
  }
}

For me this is pretty much the holy grail for i18n. Here I’ve focused on using Lingui without any other libraries, but it’s just as awesome with React. With locale files that can be plausibly handed over to a translator, and tooling that both find and remove translations Lingui has become my goto i18n library.

Flash messages for Mapbox GL JS

I’ve been working on an application where I’m using ArangoDB’s WITHIN_RECTANGLE function to pull up documents within the current map bounds. The obvious problem there is that the current map bounds can be very very big.

Dumping the entire contents of your database every time the map moves sounded decidedly sub-optimal to me so I decided to calculate the area within the requested bounds using Turf.js and send back an error if it’s to big.

So far so good, but I wanted a nice way to display that error message  as a notification right on the map. There are lots of ways to tackle that sort of thing, but given that this seemed very specific to the map, I thought I might take a stab at making it a mapbox-gl.js plugin.

The result is mapbox-gl-flash. Currently you would install it from github:

npm install --save mapbox-gl-flash

I’m using babel so I’ll use the ES2015 syntax and get a map going.

import mapboxgl from 'mapbox-gl'
import Flash from 'mapbox-gl-flash'

//This is mapbox's api token that it uses for it's examples
mapboxgl.accessToken = 'pk.eyJ1IjoibWlrZXdpbGxpYW1zb24iLCJhIjoibzRCYUlGSSJ9.QGvlt6Opm5futGhE5i-1kw';
var map = new mapboxgl.Map({
    container: 'map', // container id
    style: 'mapbox://styles/mapbox/streets-v8', //stylesheet location
    center: [-74.50, 40], // starting position
    zoom: 9 // starting zoom
});

// And now set up flash:
map.addControl(new Flash());

This sets up an element on the map that listens for a “mapbox.setflash” event.

Next the element that is listening has a class of .flash-message, so lets set up a little basic styling for it:

.flash-message {
  font-family: 'Ubuntu', sans-serif;
  position: relative;
  text-align: center;
  color: #fff;
  margin: 0;
  padding: 0.5em;
  background-color: grey;
}

.flash-message.info {
  background-color: DarkSeaGreen;
}

.flash-message.warn {
  background-color: Khaki;
}

.flash-message.error {
  background-color: LightCoral;
}

With that done lets fire an CustomEvent and see what it does.

document.dispatchEvent(new CustomEvent('mapbox.setflash', {detail: {message: "foo"}}))

foo_message

Ruby on Rails has three different kinds of flash messages: info, warn and error. That seems pretty reasonable so I’ve implemented that here as well. We’ve already set up some basic styles for those classes above and we can apply one of those classes by adding another option to out custom event detail object:

document.dispatchEvent(new CustomEvent('mapbox.setflash', {detail: {message: "foo", info: true}}))

document.dispatchEvent(new CustomEvent('mapbox.setflash', {detail: {message: "foo", warn: true}}))

document.dispatchEvent(new CustomEvent('mapbox.setflash', {detail: {message: "foo", error: true}}))

These events add the specified class to the flash message.

flash_message_classes

One final thing that I expect is for the flash message to fade out after a specified number of seconds. The is accomplished by adding a fadeout attribute:


document.dispatchEvent(new CustomEvent('mapbox.setflash', {detail: {message: "foo", fadeout: 3}}))

Lastly you can make the message go away by firing the event again with an empty string.

With a little CSS twiddling I was able to get the nice user-friendly notification I had in mind to let people know why there is no more data showing up.

flash-message

I’m pretty happy with how this turned out. Now I have a nice map specific notification that not only works in this project, but is going to be easy to add to future ones too.

A quick tour of Arangojs

I’ve been using ArangoDB for a while now, but for most of that time I’ve been using it from Ruby. I’ve dabbled with the Guacamole library and even took a crack at writing my own, but switching to Javascript has led me to get to know Arangojs.

Given that Arangojs is talking to ArangoDB via its HTTP API, basically everything you do is asynchronous. There are a few ways of dealing with async code in Javascript, and Arangojs has been written to support basically all of them.

Arangojs’s flexibility and my inexperience with the new Javascript syntax combined to give me bit of an awkward start, so with a little learning under my belt I thought I would write up some examples that would have saved me some time.

My most common use case is running an AQL query, so lets use that as an example. First up, I’ve been saving my config in a separate file:

// arango_config.js
//Using auth your url would look like:
// "http://uname:[email protected]:8529"
module.exports = {
  "production" : {
    "databaseName": process.env.PROD_DB_NAME,
    "url": process.env.PROD_DB_HOST,
  },
  "development" : {
    "databaseName": process.env.DEVELOPMENT_DB_NAME,
    "url": process.env.DEVELOPMENT_URL
  },
  "test" : {
    "databaseName": "test",
    "url": "http://127.0.0.1:8529",
  },
}

With that I can connect to one of my existing databases like so:

var config = require('../arangodb_config')[process.env.NODE_ENV]
var db = require('arangojs')(config)

This keeps my test database nicely separated from everything else and all my db credentials in the environment and out of my project code.

Assuming that our test db has a collection called “documents” containing a single document, we can use Arangojs to go get it:

db.query('FOR doc IN documents RETURN doc', function(err, cursor) {
  cursor.all(function(err, result) {
    console.log(result)
  })
})

Which returns:

[ { foo: 'bar',
    _id: 'documents/206191358605',
    _rev: '206192931469',
    _key: '206191358605' } ]

While this is perfectly valid Javascript, its pretty old-school at this point since ECMAScript 2015 is now standard in both Node.js and any browser worth having. This means we can get rid of the “function” keyword and replace it with the “fat arrow” syntax and get the same result:

db.query('FOR doc IN documents RETURN doc', (err, cursor) => {
  cursor.all((err, result) => {
    console.log(result)
  })
})

So far so good but the callback style (and the callback-hell it brings) is definitely an anti-pattern. The widely cited antidote to this is promises:

db.query('FOR doc IN documents RETURN doc')
  .then((cursor) => { return cursor.all() })
  .then((doc) => { console.log(doc) });

While this code is functionally equivalent, it operates by chaining promises together. While it’s an improvement over callback-hell, after writing a bunch of this type of code, I ended up feeling like I had replaced callback hell with promise hell.

what-fresh-hell-is-this

The path back to sanity lies in ECMAScript 2016 aka ES7 and the new async/await keywords. Inside a function marked as async, you have access to an await keyword which allows you to write code that looks synchronous but does not block the event loop.

Using the babel transpiler lets us use the new ES7 syntax right now by compiling it all down to ES5/6 equivalents. Installing with npm install -g babel and running your project with babel-node is all that you need to be able to write this:

async () => {
    let cursor = await db.query('FOR doc IN documents RETURN doc')
    let result = await cursor.all()
    console.log(result)
}()

Once again we get the same result but without all the extra cruft that we would normally have to write.

One thing that is notably absent in these examples is the use of bound variables in our queries to avoid SQL injection (technically parameter injection since this is NoSQL).

So what does that look like?

async () => {
    let bindvars = {foo: "bar"}
    let cursor = await db.query('FOR doc IN documents FILTER doc.foo == @foo RETURN doc', bindvars)
    let result = await cursor.all()
    console.log(result)
}()

But Arangojs lets you go further, giving you a nice aqlQuery function based on ES6 template strings:

async () => {
    let foo = "bar"
    let aql = aqlQuery`
      FOR doc IN documents
        FILTER doc.foo == ${foo}
          RETURN doc
    `
    let cursor = await db.query(aql)
    let result = await cursor.all()
    console.log(result)
}()

Its pretty astounding how far that simple example has come. It’s hard to believe that it’s even the same language.
With Javascript (the language and the community) clearly in transition, Arangojs (and likely every other JS library) is compelled to support both the callback style and promises. It’s a bit surprising to see how much leeway that gives me to write some pretty sub-optimal code.

With all the above in mind, suddenly Arangojs’s async heavy API no longer feels intimidating.

The documentation for Arangojs is simple (just a long readme file) but comprehensive and there is lots more it can do. Hopefully this little exploration will help people get started with Arangojs a little more smoothly than I did.

Rethinking web development maxims

The increasing use of javascript frameworks is generating a lot of interesting discussions about some oft-quoted web development maxims. Most at issue are the ideas of progressive enhancement and unobtrusive javascript.

The argument advanced in these discussions is that we as web developers need to go back and revisit the assumptions that these maxims rest on to determine if they still have value.

To that end Tom Dale of Ember.js recently wrote a great article arguing that progressive enhancement is dead, pointing to Mozilla’s recent decision to remove the ability to disable javascript from the UI. While he makes a great argument, there are plenty of good arguments to the contrary to be found.

A more complicated question if raised by Angular.js. Doesn’t its requirement to specify behaviour via attributes on your DOM elements violate the unobtrusive javascript rule?

<div ng-click="doSomething()">...</div>

Brad Green and Shyam Sheshadri attempt to address this in their book “AngularJS” in a section called “A Few Words on Unobtrusive JavaScript”. After addressing some questions about being dependent on javascript, their finally raise (what I think of as) the main concern of unobtrusive javascript:

“5. These event handlers combine structure and behaviour. This makes your code more difficult to maintain, extend, and understand.”

Their answer to that is this:

There’s a simple acid test we can use to figure out if our system suffers from this coupling (between structure and behaviour): can we create a unit test for our app logic that doesn’t require the DOM to be present?

In Angular, yes we can write controllers containing our business logic without having references to the DOM.The problem was never in the event handlers, but rather in the way we needed to write JavaScript previously. Notice that in all the controllers we’ve written so far, here and elsewhere in this book, there are no references to the DOM or DOM events anywhere.

I’m still pondering that one. I’ve used Angular on a project and then removed it and I can tell you that it sure felt a lot like coupling to have to go and remove all the ng-whatever’s sprinkled throughout all of my views.

Misgivings aside, it’s definitely a good thing to go back and revisit the facts our conclusions rest on. Like the rest of life, there is unlikely to be a single shining “right answer”, but I think this is a conversation people in the web development world should be following.

Matrix transforms in SVG

Using a matrix to transform an element is a pretty big thing in SVG. Sadly most of the tutorials I have seen either trying to introduce you to matrix math or just omit dealing with matricies at all. This is a pretty sad state of affairs, so after needing to figure this out for one of my projects I figure I would try to fill that gap a little to make things easier next time I need to deal with this.

To keep this clear lets use an small set of elements:

<html>
<body>
<svg xmlns="http://www.w3.org/2000/svg">
  <g transform="scale(0.5)">
  <rect transform="translate(50,50)" id="rect" x=0 y=0 height=50 width=50 fill="blue" />
    </g>
  </svg>
</body>
</html>

A transform applied to a parent element will cascade down to its child elements. This means that in our example here the rect element in the middle will be both scaled AND translated since the scale(0.5) also applies to it.
With that in mind you can get a matrix that represents the sum of all the transformations on a given element by calling the getCTM (the Current Transformation Matrix) function:

svg = document.querySelector('svg') // the svg root element holds many helper functions we will need.
rect = document.querySelector("rect")
​​currentMatrix = rect.getCTM()
>SVGMatrix {f: 1.2132034355964265, e: -17.071067811865476, d: 1.4142135623730951, c: -1.414213562373095, b: 1.414213562373095…}

All SVG objects also have a list of transforms that have been applied to them. You can access it with the transform property:

rect.transform
>SVGAnimatedTransformList {animVal: SVGTransformList, baseVal: SVGTransformList}

So the goal it to manipulate that list to get the effect you are looking for. The least complicated thing you can do is simply append another transform to the existing list of transforms:

newTransform = svg.createSVGTransformFromMatrix(svg.createSVGMatrix().translate(150,50))
rect.transform.baseVal.appendItem(newTransform)

This will move the rect element 150 px to the left and 50 px down.

The other way to approach this would be to replace the existing transform(s) with a single new transform. You can accomplish that with the initialize function.:

rect.transform.baseVal.initialize(newTransform)

If we wanted to move our element to 750px while keeping everything else the same (and replacing all existing transforms), it might look something like this:

current_matrix = rect.getCTM()
>SVGMatrix {f: 25, e: 25, d: 0.5, c: 0, b: 0…}&amp;lt;/div&amp;gt;
transformed_matrix = current_matrix.inverse().multiply(svg.createSVGMatrix().translate(750, 50).scale(0.5))
>SVGMatrix {f: 50, e: 1450, d: 1, c: 0, b: 0…}
rect.transform.baseVal.initialize(svg.createSVGTransformFromMatrix(transformed_matrix))
>SVGTransform {angle: 0, matrix: SVGMatrix, type: 1, setMatrix: function, setTranslate: function…}

Matricies can be a little hard on the head and understanding SOME matrix multiplication is very helpful. The tricky part is learning enough so you can get your project done without having to redo your whole high-school math curriculum. The best resource for a concise explanation is Coursera’s Machine Learning course. Check out the linear algebra review in section 3. He gets right down to business and explains it all really clearly.

Javascript and the end of history (of programming languages)

In 1989 Francis Fukuyama published the essay “The end of history?” which says:

What we may be witnessing is not just the end of the Cold War, or the passing of a particular period of postwar history, but the end of history as such: that is, the end point of mankind’s ideological evolution and the universalization of Western liberal democracy as the final form of human government.

I am not the first to notice that the programming world seems to be undergoing a similar shift, with the universalization of Javascript and its seeming adoption as the final form of programming.

The Mozilla platform (XUL, XPCOM, etc…) has long made it possible to develop desktop applications in Javascript (Firefox most famously) but radical changes have been afoot. Microsoft and the Gnome Foundation have both made Javascript their a central development language. On the mobile front Apache Cordova (formerly Phonegap), Firefox OS and other projects are ensuring steady growth of Javascript there.

Of course Node.js means that your server side code can now be written in Javascript as well. If you are wondering if how that is going, consider that Modulecounts reports that the npm package repository is growing faster even than Rubygems. On top of all that HTML 5 and standards like WebRTC and WebGL ensure that Javascript grows ever more powerful in the browser as well.

This is a curious shift to watch. Javascript is a pretty surprising choice for the “final form” of programming but here it is anyway, its adoption driven presumably by the number or programmers familiar with it from working with the DOM. Microsoft’s adoption seems is doubly curious; what would be the difference between Firefox OS and Windows when all/most apps are written in Javascript? It’s as though they are embracing Marc Andreessen’s famous prediction that “Windows will just be a buggy set of device drivers” and adding “and a Javascript API!”.

Does all this really spell the end for other languages? Is Javascript really taking over the world? It’s hard not to feel that way.

The famous philosopher Slavoj Žižek points out that where we used to see demands for Western-style democracy after every introduction of capitalism (and thus thought there was causation not just correlation), we are starting to see capitalism appear in stronger forms without democracy, giving a new form of political organisation. What he is getting at is that Fukuyama was wrong, history marches onwards after all.

When I look at projects on the border between Javascript and Ruby where authors are pressing each languages strengths and compensating for weaknesses, I think there is plenty more history to come in the world of programming. It just looks like the path to get there is going to be dominated by Javascript.