diff --git a/@commitlint/rules/src/subject-case.test.ts b/@commitlint/rules/src/subject-case.test.ts
index 55a6158e44..ac4b15d769 100644
--- a/@commitlint/rules/src/subject-case.test.ts
+++ b/@commitlint/rules/src/subject-case.test.ts
@@ -5,26 +5,44 @@ const messages = {
 	empty: 'test:\n',
 	numeric: 'test: 1.0.0',
 	lowercase: 'test: subject',
+	lowercase_unicode: 'test: тема', // Bulgarian for `subject`
 	mixedcase: 'test: sUbJeCt',
 	uppercase: 'test: SUBJECT',
+	uppercase_unicode: 'test: ÛNDERWERP', // Frisian for `SUBJECT`
 	camelcase: 'test: subJect',
+	camelcase_unicode: 'test: θέΜα', // Greek for `subJect`
 	kebabcase: 'test: sub-ject',
+	kebabcase_unicode: 'test: áb-har', // Irish for `sub-ject`
 	pascalcase: 'test: SubJect',
+	pascalcase_unicode: 'test: ТақыРып', // Kazakh for `SubJect`
 	snakecase: 'test: sub_ject',
+	snakecase_unicode: 'test: сэ_дэв', // Mongolian for `sub_ject`
 	startcase: 'test: Sub Ject',
+	startcase_unicode: 'test: Äm Ne', // Swedish for `Sub Ject`
+	sentencecase: 'test: Sub ject',
+	sentencecase_unicode: 'test: Мав зуъ', // Tajik for `Sub ject`
 };
 
 const parsed = {
 	empty: parse(messages.empty),
 	numeric: parse(messages.numeric),
 	lowercase: parse(messages.lowercase),
+	lowercase_unicode: parse(messages.lowercase_unicode),
 	mixedcase: parse(messages.mixedcase),
 	uppercase: parse(messages.uppercase),
+	uppercase_unicode: parse(messages.uppercase_unicode),
 	camelcase: parse(messages.camelcase),
+	camelcase_unicode: parse(messages.camelcase_unicode),
 	kebabcase: parse(messages.kebabcase),
+	kebabcase_unicode: parse(messages.kebabcase_unicode),
 	pascalcase: parse(messages.pascalcase),
+	pascalcase_unicode: parse(messages.pascalcase_unicode),
 	snakecase: parse(messages.snakecase),
+	snakecase_unicode: parse(messages.snakecase_unicode),
 	startcase: parse(messages.startcase),
+	startcase_unicode: parse(messages.startcase_unicode),
+	sentencecase: parse(messages.sentencecase),
+	sentencecase_unicode: parse(messages.sentencecase_unicode),
 };
 
 test('with empty subject should succeed for "never lowercase"', async () => {
@@ -63,6 +81,16 @@ test('with lowercase subject should succeed for "always lowercase"', async () =>
 	expect(actual).toEqual(expected);
 });
 
+test('with lowercase unicode subject should fail for "always uppercase"', async () => {
+	const [actual] = subjectCase(
+		await parsed.lowercase_unicode,
+		'always',
+		'upper-case'
+	);
+	const expected = false;
+	expect(actual).toEqual(expected);
+});
+
 test('with mixedcase subject should succeed for "never lowercase"', async () => {
 	const [actual] = subjectCase(await parsed.mixedcase, 'never', 'lowercase');
 	const expected = true;
@@ -93,12 +121,22 @@ test('with uppercase subject should fail for "never uppercase"', async () => {
 	expect(actual).toEqual(expected);
 });
 
-test('with lowercase subject should succeed for "always uppercase"', async () => {
+test('with uppercase subject should succeed for "always uppercase"', async () => {
 	const [actual] = subjectCase(await parsed.uppercase, 'always', 'uppercase');
 	const expected = true;
 	expect(actual).toEqual(expected);
 });
 
+test('with uppercase unicode subject should fail for "always lowercase"', async () => {
+	const [actual] = subjectCase(
+		await parsed.uppercase_unicode,
+		'always',
+		'lower-case'
+	);
+	const expected = false;
+	expect(actual).toEqual(expected);
+});
+
 test('with camelcase subject should fail for "always uppercase"', async () => {
 	const [actual] = subjectCase(await parsed.camelcase, 'always', 'uppercase');
 	const expected = false;
@@ -135,6 +173,26 @@ test('with camelcase subject should succeed for "always camelcase"', async () =>
 	expect(actual).toEqual(expected);
 });
 
+test('with camelcase unicode subject should fail for "always sentencecase"', async () => {
+	const [actual] = subjectCase(
+		await parsed.camelcase_unicode,
+		'always',
+		'sentence-case'
+	);
+	const expected = false;
+	expect(actual).toEqual(expected);
+});
+
+test('with kebabcase unicode subject should fail for "always camelcase"', async () => {
+	const [actual] = subjectCase(
+		await parsed.kebabcase_unicode,
+		'always',
+		'camel-case'
+	);
+	const expected = false;
+	expect(actual).toEqual(expected);
+});
+
 test('with pascalcase subject should fail for "always uppercase"', async () => {
 	const [actual] = subjectCase(await parsed.pascalcase, 'always', 'uppercase');
 	const expected = false;
@@ -175,6 +233,16 @@ test('with pascalcase subject should fail for "always camelcase"', async () => {
 	expect(actual).toEqual(expected);
 });
 
+test('with pascalcase unicode subject should fail for "always uppercase"', async () => {
+	const [actual] = subjectCase(
+		await parsed.pascalcase_unicode,
+		'always',
+		'upper-case'
+	);
+	const expected = false;
+	expect(actual).toEqual(expected);
+});
+
 test('with snakecase subject should fail for "always uppercase"', async () => {
 	const [actual] = subjectCase(await parsed.snakecase, 'always', 'uppercase');
 	const expected = false;
@@ -211,6 +279,16 @@ test('with snakecase subject should fail for "always camelcase"', async () => {
 	expect(actual).toEqual(expected);
 });
 
+test('with snakecase unicode subject should fail for "never lowercase"', async () => {
+	const [actual] = subjectCase(
+		await parsed.snakecase_unicode,
+		'never',
+		'lower-case'
+	);
+	const expected = false;
+	expect(actual).toEqual(expected);
+});
+
 test('with startcase subject should fail for "always uppercase"', async () => {
 	const [actual] = subjectCase(await parsed.startcase, 'always', 'uppercase');
 	const expected = false;
@@ -253,6 +331,66 @@ test('with startcase subject should succeed for "always startcase"', async () =>
 	expect(actual).toEqual(expected);
 });
 
+test('with startcase unicode subject should fail for "always pascalcase"', async () => {
+	const [actual] = subjectCase(
+		await parsed.startcase_unicode,
+		'always',
+		'pascal-case'
+	);
+	const expected = false;
+	expect(actual).toEqual(expected);
+});
+
+test('with sentencecase subject should succeed for "always sentence-case"', async () => {
+	const [actual] = subjectCase(
+		await parsed.sentencecase,
+		'always',
+		'sentence-case'
+	);
+	const expected = true;
+	expect(actual).toEqual(expected);
+});
+
+test('with sentencecase subject should fail for "never sentencecase"', async () => {
+	const [actual] = subjectCase(
+		await parsed.sentencecase,
+		'never',
+		'sentence-case'
+	);
+	const expected = false;
+	expect(actual).toEqual(expected);
+});
+
+test('with sentencecase subject should fail for "always pascalcase"', async () => {
+	const [actual] = subjectCase(
+		await parsed.sentencecase,
+		'always',
+		'pascal-case'
+	);
+	const expected = false;
+	expect(actual).toEqual(expected);
+});
+
+test('with sentencecase subject should succeed for "never camelcase"', async () => {
+	const [actual] = subjectCase(
+		await parsed.sentencecase,
+		'never',
+		'camel-case'
+	);
+	const expected = true;
+	expect(actual).toEqual(expected);
+});
+
+test('with sentencecase unicode subject should fail for "always camelcase"', async () => {
+	const [actual] = subjectCase(
+		await parsed.sentencecase_unicode,
+		'always',
+		'camel-case'
+	);
+	const expected = false;
+	expect(actual).toEqual(expected);
+});
+
 test('should use expected message with "always"', async () => {
 	const [, message] = subjectCase(
 		await parsed.uppercase,
diff --git a/@commitlint/rules/src/subject-case.ts b/@commitlint/rules/src/subject-case.ts
index a993af5af1..1b66bce291 100644
--- a/@commitlint/rules/src/subject-case.ts
+++ b/@commitlint/rules/src/subject-case.ts
@@ -2,6 +2,23 @@ import {case as ensureCase} from '@commitlint/ensure';
 import message from '@commitlint/message';
 import {TargetCaseType, SyncRule} from '@commitlint/types';
 
+/**
+ * Since the rule requires first symbol of a subject to be a letter, use
+ * combination of Unicode `Cased_Letter` and `Other_Letter` categories now to
+ * allow non-Latin alphabets as well.
+ *
+ * Do not use `Letter` category directly to avoid capturing `Modifier_Letter`
+ * (which just modifiers letters, so we probably shouldn't anyway) and to stay
+ * close to previous implementation.
+ *
+ * Also, typescript does not seem to support almost any longhand category name
+ * (and even short for `Cased_Letter` too) so list all required letter
+ * categories manually just to prevent it from complaining about unknown stuff.
+ *
+ * @see [Unicode Categories]{@link https://www.regular-expressions.info/unicode.html}
+ */
+const startsWithLetterRegex = /^[\p{Ll}\p{Lu}\p{Lt}\p{Lo}]/iu;
+
 const negated = (when?: string) => when === 'never';
 
 export const subjectCase: SyncRule<TargetCaseType | TargetCaseType[]> = (
@@ -11,7 +28,7 @@ export const subjectCase: SyncRule<TargetCaseType | TargetCaseType[]> = (
 ) => {
 	const {subject} = parsed;
 
-	if (typeof subject !== 'string' || !subject.match(/^[a-z]/i)) {
+	if (typeof subject !== 'string' || !subject.match(startsWithLetterRegex)) {
 		return [true];
 	}