Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion examples/01-basic/10-localization/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Localization (i18n)

In this example, we pass in a custom dictionary to change the interface of the editor to use Dutch (NL) strings.
In this example, we use a dropdown to switch the editor between all of the languages that BlockNote ships with, by passing the matching dictionary from `@blocknote/core/locales` to the editor. Selecting a language re-mounts the editor so the interface strings update immediately.

You can also provide your own dictionary to customize the strings used in the editor, or submit a Pull Request to add support for your language of your choice.

Expand Down
86 changes: 72 additions & 14 deletions examples/01-basic/10-localization/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,79 @@
import { nl } from "@blocknote/core/locales";
import type { Dictionary } from "@blocknote/core";
import * as locales from "@blocknote/core/locales";
import "@blocknote/core/fonts/inter.css";
import { BlockNoteView } from "@blocknote/mantine";
import "@blocknote/mantine/style.css";
import { useCreateBlockNote } from "@blocknote/react";
// import { useTranslation } from "some-i18n-library"; // You can use any i18n library you like
import { useState } from "react";

// Every dictionary exported by `@blocknote/core/locales`, keyed by its
// language code (the same key used in the export, e.g. `zhTW`).
const dictionaries: Record<string, Dictionary> = locales;

// Human-readable names shown in the language picker.
const languageNames: Record<string, string> = {
ar: "العربية",
de: "Deutsch",
en: "English",
es: "Español",
fa: "فارسی",
fr: "Français",
he: "עברית",
hr: "Hrvatski",
is: "Íslenska",
it: "Italiano",
ja: "日本語",
ko: "한국어",
nl: "Nederlands",
no: "Norsk",
pl: "Polski",
pt: "Português",
ru: "Русский",
sk: "Slovenčina",
tr: "Türkçe",
uk: "Українська",
uz: "Oʻzbekcha",
vi: "Tiếng Việt",
zh: "简体中文",
zhTW: "繁體中文",
};

const languageKeys = Object.keys(dictionaries).sort((a, b) =>
(languageNames[a] ?? a).localeCompare(languageNames[b] ?? b),
);

// Creates the editor with the given dictionary. This is a separate component so
// that changing its `key` (see below) re-mounts it, re-creating the editor
// instance with the newly selected language.
function LocalizedEditor(props: { dictionary: Dictionary }) {
const editor = useCreateBlockNote({ dictionary: props.dictionary });

export default function App() {
// const { lang } = useTranslation('common'); // You can get the current language from the i18n library or alternatively from a router
// Creates a new editor instance.
const editor = useCreateBlockNote({
// Passes the Dutch (NL) dictionary to the editor instance.
// You can also provide your own dictionary here to customize the strings used in the editor,
// or submit a Pull Request to add support for your language of your choice
dictionary: nl,
// dictionary: locales[lang as keyof typeof locales], // Use the language from the i18n library dynamically
});

// Renders the editor instance using a React component.
return <BlockNoteView editor={editor} />;
}

export default function App() {
// The currently selected language.
const [language, setLanguage] = useState<keyof typeof dictionaries>("en");

return (
<div>
<label>
Language:{" "}
<select
value={language}
onChange={(event) => setLanguage(event.target.value)}
>
{languageKeys.map((key) => (
<option key={key} value={key}>
{languageNames[key] ?? key}
</option>
))}
</select>
</label>

{/* Keying the editor by the language re-mounts it whenever the selection
changes, so the editor picks up the newly selected dictionary. */}
<LocalizedEditor key={language} dictionary={dictionaries[language]} />
</div>
);
}
41 changes: 41 additions & 0 deletions packages/core/NOTICE.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
BlockNote Core Third-Party Notices

Unicode CLDR annotation data
----------------------------

The generated emoji locale data under src/emoji-data/frimousse includes
annotations derived from Unicode CLDR 48.2.0. The source is the Unicode
Consortium's unicode-org/cldr-json repository:

https://github.com/unicode-org/cldr-json

The CLDR annotation data is licensed under the Unicode License V3:

Copyright © 1991-2025 Unicode, Inc.

Unicode License V3

Permission is hereby granted, free of charge, to any person obtaining a copy
of the Unicode Data files and associated documentation (the "Data Files") or
Unicode software and associated documentation (the "Software") to deal in the
Data Files or Software without restriction, including without limitation the
rights to use, copy, modify, merge, publish, distribute, and/or sell copies
of the Data Files or Software, and to permit persons to whom the Data Files or
Software are furnished to do so, provided that either (a) this copyright and
permission notice appear with all copies of the Data Files or Software, or (b)
this copyright and permission notice appear in associated Documentation.

THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR
CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
OF THE DATA FILES OR SOFTWARE.

Except as contained in this notice, the name of a copyright holder shall not
be used in advertising or otherwise to promote the sale, use or other dealings
in these Data Files or Software without prior written authorization of the
copyright holder.
32 changes: 28 additions & 4 deletions packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@
"files": [
"dist",
"types",
"src"
"src",
"static",
"NOTICE.txt"
],
"keywords": [
"react",
Expand Down Expand Up @@ -81,6 +83,26 @@
"types": "./types/src/y/index.d.ts",
"import": "./dist/y.js",
"require": "./dist/y.cjs"
},
"./emoji-data": {
"types": "./types/src/emoji-data/index.d.ts",
"import": "./dist/emoji-data.js",
"require": "./dist/emoji-data.cjs"
},
"./emoji-data/frimousse": {
"types": "./types/src/emoji-data/frimousse/index.d.ts",
"import": "./dist/emoji-data/frimousse.js",
"require": "./dist/emoji-data/frimousse.cjs"
},
"./emoji-data/frimousse/*": {
"types": "./types/src/emoji-data/frimousse/*.d.ts",
"import": "./dist/emoji-data/frimousse/*.js",
"require": "./dist/emoji-data/frimousse/*.cjs"
},
"./emoji-data/locales": {
"types": "./types/src/emoji-data/i18n/index.d.ts",
"import": "./dist/emoji-data/locales.js",
"require": "./dist/emoji-data/locales.cjs"
}
},
"scripts": {
Expand All @@ -91,10 +113,10 @@
"test": "vp test --run",
"test-watch": "vp test watch",
"clean": "rimraf dist && rimraf types",
"update-tlds": "node scripts/update-tlds.mjs"
"update-tlds": "node scripts/update-tlds.mjs",
"generate-emoji-data": "node scripts/emoji-data/generate.mjs"
},
"dependencies": {
"@emoji-mart/data": "^1.2.1",
"@handlewithcare/prosemirror-inputrules": "^0.1.4",
"@shikijs/types": "^4.4.3",
"@tiptap/core": "^3.31.3",
Expand All @@ -106,7 +128,6 @@
"@tiptap/extension-underline": "^3.31.3",
"@tiptap/extensions": "^3.31.3",
"@tiptap/pm": "^3.31.3",
"emoji-mart": "^5.6.0",
"fast-deep-equal": "^3.1.3",
"lib0": "1.0.0-rc.22",
"prosemirror-highlight": "^0.15.3",
Expand All @@ -117,6 +138,9 @@
"prosemirror-view": "^1.42.4"
},
"devDependencies": {
"cldr-annotations-derived-full": "48.2.0",
"cldr-annotations-full": "48.2.0",
"emojibase-data": "^16.0.1",
"jsdom": "^29.0.2",
"rimraf": "^5.0.10",
"rollup-plugin-webpack-stats": "^0.2.6",
Expand Down
Loading
Loading