preface

2021-2022, front-end development is changing with each passing day, with rising stars emerging in various directions: With the packaging tool Vite, the front-end view framework SolidJS, the back-end framework Remix, new CSS features and the TC39 proposal supported by major browsers, there is no doubt that 2022 will be the best year for JavaScript since its debut.

The TikTok Hangzhou team I work for is mainly responsible for the revenue activities of the live broadcast room. Users and anchors are encouraged to recharge and give gifts by playing ways such as ranking, doing tasks and 1V1 PK. The activities are launched in the Middle East, Europe and Southeast Asia… So internationalization is an integral part of the R&D process.

This article discusses how traditional RTL layouts, time zone transitions, and localization solutions will react with new features

Slide preview: A brief introduction to internationalization activities under the new features

How to determine RTL

We will provide the corresponding active link according to the country and region of the launch, and add the lang attribute to the URL Query Params to represent the local language:

  • Example In China: example.com? Lang =zh
  • Middle East: example.com? Lang =ar

The current logic for determining whether to apply RTL layout is as follows:

const isRTL = () = > {
  const { lang } = getQueryParams();

  return lang === "ar";
};

<div dir={isRTL() ? "rtl" : "ltr"} ></div>;
Copy the code

At first glance, the code looks fine, but from a robustness and maintainability point of view, it is flawed: lang === ar is hard-coded.

In addition to the regular ar for Arabic and zh for Chinese, the Language Code also consists of [Language]-[country/region] :

  • ar-EGArabic for Arabic (Egyptian)
  • ar-IQArabic for Arabic (Iraq)

The complete Language Code data is available in the ISO Language Code Table.

Future activities will be segmented to countries in the Middle East, however AR-eg === AR returns false and users in Egypt will only see the LTR layout, exposing the drawbacks of hard coding.

One way to optimize is through regular matching:

const RTLRegExp = /^ar/;

RTLRegExp.test("ar"); // true
RTLRegExp.test("ar-EG"); // true
RTLRegExp.test("ar-IQ"); // true
Copy the code

But is there a better way?

JavaScript V8 V9.9 added the textInfo object to Intl.locale, which returns language-sensitive text information, including the direction attribute, Is used for HTML dir attribute and CSS Direction property.

Available from Chrome 99 on the console:

new Intl.Locale("ar").textInfo;
// => {direction: 'rtl'}

new Intl.Locale("ar-EG").textInfo;
// => {direction: 'rtl'}

new Intl.Locale("he").textInfo;
// => {direction: 'rtl'}

new Intl.Locale("zh-TW").textInfo;
// => {direction: 'ltr'}

new Intl.Locale("ja-JP").textInfo;
// => {direction: 'ltr'}
Copy the code

With the JavaScript Built-in API, the problem of how to determine RTL is solved.

RTL layout fits the final solution

Earlier, I introduced the elegant solution to RTL layout adaptation using Sass. The idea is to override the default (LTR) style by applying THE RTL style to the elements that need to be adapted to RTL through the HTML dir attribute.

.demo {
  left: 10px;

  @include dir("rtl") {
    left: unset;
    right: 10px; }}Copy the code

Compiled CSS:

.demo {
  left: 10px;
}

[dir="rtl"] .demo {
  left: unset;
  right: 10px;
}
Copy the code

While the @mixin and @include features provided by Sass allow developers to write CSS without reprogramming, the compiled CSS code does not disappear.

Not only that, but for every element that fits RTL, we have to write a mirror style and erase the previous style, which adds to our burden.

Admittedly, from practical, compatibility considerations, the above is the most “elegant” scheme.

I was browsing MDN the other day and came across CSS Logical Properties and Values, which is the ultimate RTL fit layout solution.

The logical properties and values of the CSS are a module of the CSS. The imported properties and values control the layout logically rather than physically, directionally, or dimensionally.

I’ll take 🌰. Now the UI requires us to set the left and right interior margin of div.box to 10px. The padding is used as one of the type of dictate properties.

div.box {
  padding: 0 10px;
}
Copy the code

Obviously, the padding on div.box is set to 0, which is not what we would expect if there were style overwriting problems in complex scenes.

This is where the padding-inline in CSS Logical Properties and Values comes in, which is also a shorthand property and consists of two Properties:

  • padding-inline-end
  • padding-inline-start

It defines an element with a starting and trailing inner margin in the inline direction at the logical level.

HTML elements are roughly inline, meaning the same line, and block-level, meaning the same column. Try to define multiple < SPAN >hello and

hello

in HTML. See if they’re arranged in a row or a row.

div.box {
  /* Equivalent to the padding: 0 10px */ without other rules
  padding-inline: 10px;
}
Copy the code

What does this have to do with RTL layout? The word “logical level” in the previous definition is important because the logical direction can change, whereas top, right, bottom, and left are purely physical directions that never change.

As we know, motion is relative, and you have to choose the right reference to determine whether an object is moving or not, and the choice of reference makes a difference.

The logical properties of CSS also work the same way, depending on the “reference” of the current element, such as writing mode and element arrangement direction.

IO /b2d1/pen/vY…

As you can see, the default layout under padding-inline-start is padding-left, whereas when you declare writing-mode: After vertical-LR, padding-inline-start is padding-top, which is where CSS Logical Properties and Values stand out.

.text {
  padding-inline-start: 20px;
  border: 1px solid;
}

.text-vertical {
  padding-inline-start: 20px;
  writing-mode: vertical-lr;
  border: 1px solid;
}
Copy the code

So RTL layout can be implemented without awareness, no need to write complex image style, just give dir, the browser will automatically adjust the logical direction.

Check out the online example on CodePen: codepen. IO /b2d1/pen/qB…

Padding-inline-start changes to padding-left and padding-right in the physical direction, depending on the direction.

.text {
  padding-inline-start: 20px;
  border: 1px solid;
}

.text-rtl {
  direction: rtl;
  padding-inline-start: 20px;
  border: 1px solid;
}
Copy the code

About the INTL

The full name for INTL is internationalization. It is also called I18N because there are 18 words between the word “I” and “n”.

As an implementation of the ECMA-262 specification, JavaScript’s internationalization capability is defined by the ECMA-402 specification, implemented by the JavaScript standard built-in global object Intl and provides a series of language-sensitive apis.

Here are a few uses to give you a taste.

Format the list with the mainland Chinese hyphen “and” :

new Intl.ListFormat("zh-CN", {
  type: "conjunction",
}).format(["Jiangnan at Night"."Drizzle"."Oil-paper umbrella"."You"]);

// => Night jiangnan, drizzle, oil-paper umbrella and you
Copy the code

Using Taiwan 12-hour format time:

new Intl.DateTimeFormat("zh-Hant-TW", {
  hour: "numeric".hourCycle: "h12",
}).format(new Date());
// => 1 am
Copy the code

Format numbers using mainland Chinese currency format:

new Intl.NumberFormat("zh-CN", {
  style: "currency".currency: "CNY",
}).format(19980521);
/ / = > selections 19980521.00
Copy the code

Get the traditional Calendar of Mainland China:

new Intl.DisplayNames(["zh-CN"] and {type: "calendar" }).of("chinese");
/ / = > the lunar calendar
Copy the code

Get the time zone name of Hong Kong, China:

new Intl.Locale("zh-HK").timeZones;
// => ['Asia/Hong_Kong']
Copy the code

How to Change Time Zones

Timestamp = 1643767200000 = 2022/02/02 02:00 (GMT+0)

When visiting Japan’s active page in China (GMT+8), it is required to display the Japanese local time (2022/02/02 11:00), not the Chinese time (2022/2/2 10:00), so we need to use the tool function to switch the time zone:

export function formatUtcToLocal(timestamp: number, utcValue: number) {
  const timeOffset = new Date().getTimezoneOffset() * 60;
  const result =
    Math.floor(timestamp / 1000 + timeOffset + (utcValue || 0) * 60) * 1000;
  return result;
}

new Date(formatUtcToLocal(1643767200000.9 * 60)).toLocaleString();

/ / = > 2022/2/2 11:00:00
Copy the code

The 🧐 code is only a few lines long, but it’s hard to read, and it’s a simple base scenario.

There is no doubt that JavaScript’s built-in Date object is a bad design.

Problems with Date:

  1. Time zones other than the user’s local time are not supported
  2. Missing computing API

In business, the complex time zone conversion and time calculation can only be realized with the help of community open source libraries such as moment.js and day.js.

The TC39 organization also realized that Date objects should be phased out, so they invited Maggie, author of moment. Js, to lead the design of the new feature Temporal, which is currently in Stage 3.

A complete Temporal consists of three parts:

  1. ISO 8601 International time format, in which T is the separator of the date (2020-08-05) and time (20:06:13). + indicates the Eastern time zone, and – indicates the Western time zone
  2. Name of time Zone (Tokyo, Japan)
  3. Calendar (Japanese calendar)

With the help of Temporal, getting the local time in Japan is easy:

Temporal.Instant.from(new Date(1643767200000).toISOString())
  .toZonedDateTimeISO("+ 09:00")
  .toString();

// => 2022-02-02T11:00:00+09:00
Copy the code

Using Temporal’s calculation API:

dt = Temporal.PlainDateTime.from("1995-12-07T03:24:30");
dt.add({ years: 20.months: 4.hours: 5.minutes: 6 });

// => 2016-04-07T08:30:30
Copy the code
const duration = Temporal.Duration.from({
  hours: 130.minutes: 20}); duration.total({unit: "second" });

/ / = > 469200
Copy the code

Because Temporal features are not supported by mainstream browsers, you need to open tc39. Es /proposal-te… The console runs the code above and the site has been introduced by Polyfill.

At the end

Although CSS Logical Properties and Values and Intl have high requirements for browser compatibility, even Temporal is not supported at the present stage…

I can still be confident that I can use it in a production environment while downgrading it, which is what I’ve always pursued as a geek, and conformism has never been the creed of Web developers.