SPFx Check Locale - a nice option to check your localization consistency across SharePoint Framework solution

If you develop multi-lingual SharePoint Framework solutions, you know that you should keep your localization files in sync. You have a "master" file, which defines your localization resources structure, by default it's called "mystrings.d.ts" where you define all different keys. In the corresponding {locale}.js file you implement actual translations. In some cases, when you have a lot of labels after the refactoring you might lose the synchronization between your "mystrings.d.ts" and JS resource files. That leads to empty labels and UI problems in your web parts. SPFx doesn't provide a mechanism to check it. 

Now you can use SPFx Check Locale VSCode add-in and a Nodejs module to perform such checks. 

VSCode

You can install the addin from here or just search in VScode for "SPFx Check Locale".

The below video describes the core features of the addin: 

If you have and differences between your maser "mystrings.d.ts" and {locale}.js resource, the error will be immediately reported (including line and message). Using the addin you now have a clear visual indication that something is wrong with your localization files. 

Nodejs

You can also integrate SPFx check-locale as an additional quality check into your build pipeline since it's also available as a nodejs module

Install "spfx-check-locale" module and just add the below code to your gulpfile.js:

const checkLocales = require('spfx-check-locale').checkForErrors;

const argv = build.rig.getYargs().argv;
if (argv.production) {
  const check = build.subTask('check-locales', function (gulp, buildOptions, done) {
    checkLocales({
      projectPath: __dirname,
      printErrors: true
    })
      .then(result => {
        if (result.diagnosticData.length === 0) {
          done();
        } else {
          done('Found errors in localization files');
        }
      }).catch(done);
  });

  build.rig.addPostBuildTask(build.task('check-locales', check));
}

That way before publishing to production you always sure that your resources are good, otherwise your build will fail. The above code performs locale checks only on production builds (argv.production, which is true for gulp bundle --ship). You can also do it on a normal gulp serve, however, it will slow down your build for additional 2-4 seconds. With VSCode add-in it doesn't make a lot of sense to have it in serve command. 

"spfx-check-locale" integrates smoothly with your CI\CD process as well.

How it works

Every SharePoint Framework project contains a config.json file, which lists localizedResources - a collection of project resources. spfx-check-locale module opens every folder with resources and extracts interface name from "mystrings.d.ts" (using TypeScript AST). Then it creates a virtual TypeScript project in memory adding all files inside the resources folder. {locale}.js are renamed to {locale}.ts. For every {locale}.ts it also adds a return value for a function to be equal to the interface name from "mystrings.d.ts". 

For example, a en-us.ts will look like below:

define([], function(): IHelloWorldWebPartStrings {
  return {
    "PropertyPaneDescription": "Description",
    "BasicGroupName": "Group Name",
    "DescriptionFieldLabel": "Description Field"
  }
});

Next, the module runs TS compilation in memory and VSCode add-in simply maps TS errors to the corresponding lines inside IDE. That way we can see all problems in a real time. 

Title image credits - People vector created by pch.vector - www.freepik.com

Introducing SharePoint Typed Item - Visual Studio Code extension

When working with SharePoint as a developer you often need access to SharePoint data. If you use TypeScript you expect that all data will be strongly typed. However, it's not a case if you work with SharePoint dynamic data like lists and libraries. 

Consider the code below written with PnPjs:

sp.web.lists.getByTitle('Clients').items.get()
      .then((items: any[]) => {
        for (const item of items) {
          console.log(item);
        }
      });

or with SPHttpClient inside SharePoint Framework solution: 

this.context.spHttpClient.get(`${currentWebUrl}/_api/web/lists/getByTitle('Clients')/items`, SPHttpClient.configurations.v1)
      .then((response: SPHttpClientResponse) => {
        response.json().then((items: any[]) => {
          for (const item of items) {
            console.log(item);
          }
        });
      });

In both cases, you don't know the type of items beforehand and have to use any type (items: any[]). What's wrong with any type? In TypeScript it's considered as bad practice. Of course you can and should use any in some edge cases, but in general, it's considered as bad. With any type you don't have type intellisense in vscode, you lose type checking if you want to use your variable elsewhere. So how to fix it? 

To fix it you should create a separate interface manually and describe all needed fields. In that case instead of any you use: 

items: Client[]

While it works, it has a few drawbacks: 

  • you have to create all needed interfaces manually
  • if you have a need to access additional fields, you will have to go and update corresponding interfaces
  • if you (or team members) add a field to a list, you will have to go and update corresponding interfaces

What if there is a tool, which generates all required always up-to-date interfaces for you?

This is exactly what SharePoint Typed Item does - it takes your configuration and outputs TypeScript interfaces based on SharePoint lists, libraries and content types. 

Read further to find out how to get started with SharePoint Typed Item extension. More...