From 6f8fdae7c508c31628330d9fb5f0a690ac62dcdb Mon Sep 17 00:00:00 2001
From: Darcy Wong
Date: Tue, 24 Mar 2026 16:11:55 +0700
Subject: [PATCH 01/38] fix: .htaccess for including in the URL
* From rubber-ducky with MD
---
.htaccess | 23 +++++++++++++++++++----
1 file changed, 19 insertions(+), 4 deletions(-)
diff --git a/.htaccess b/.htaccess
index 05cecb6d..1d5f1882 100644
--- a/.htaccess
+++ b/.htaccess
@@ -32,6 +32,11 @@ RewriteRule ^crowdin.yml$ = [F,L]
# apple-app-site-association
RewriteRule "^.well-known/apple-app-site-association$" "/.well-known/apple-app-site-association.json" [L]
+# Rewrite //... ignoring known 2-3 letter folders
+#RewriteCond "$1" !-f
+#RewriteCond "$1" !-d
+#RewriteRule "^/(?!cdn|go|mac|web)/(.+)?/" "/_content/$2?lang=$1"
+
# macosx and macos to mac (ignore case)
RewriteRule "^(macosx|macos)\b(.*)$" "/mac$2" [NC,R=301,END,QSA]
@@ -180,8 +185,17 @@ RedirectMatch "^/(french|german|italian|spanish|swedish)(/?)$" "/keyboards
# dedicated-keyboard-landing pages
RedirectMatch 301 "^/(amharic|burmese|cameroon|ethiopic|eurolatin|greek|ipa|sinhala|tamil|tibetan|tigrigna|urdu)(/.*)?$" "/keyboards/h/$1$2"
+
#
-# PHP and Markdown rewriting
+# if $1 is a folder or file in /_content, then redirect to currentlang (en?)
+# e.g. would redirect windows/download --> en/windows/download/
+RewriteCond "{$DOCUMENT_ROOT}/_content/$1.php" -f
+RewriteRule "^(.+)" "en/$1" [R,L]
+
+# TODO: do we want en/lao --> en/keyboards/basic_kbdlao? as well as /lao --> ...
+
+#
+# PHP and Markdown redirections
#
# Remove index or index.php and redirect (and stop processing)
@@ -200,14 +214,15 @@ RewriteCond "{DOCUMENT_ROOT}/$1.md" !-f
RewriteRule "^(.+[^/])$" "$1/" [R,END]
#
-# PHP rewriting
+# PHP and Markdown rewriting
#
# TODO: mdhost currently in a different path than help.keyman
# Rewrite file to file.md
-RewriteCond "%{DOCUMENT_ROOT}/$1.md" -f
-RewriteRule "^(.+)$" "/_includes/includes/md/mdhost.php?file=$1.md" [END]
+RewriteCond "%{DOCUMENT_ROOT}/_content/$2.md" -f
+# en --> should be a bcp-47 type 'lang' match (e.g. ab[-x][-y]) ignore case, keep it a fairly loose expression [a-z][a-z][a-z]?(-...)?
+RewriteRule "^(en)/(.+)$" "/_includes/includes/md/mdhost.php?file=_content/$2.md&lang=$1" [END]
# Rewrite file to file.php
RewriteCond "%{DOCUMENT_ROOT}/$1.php" -f
From 863f677d3c3566117dfba11203639dc6b6393e30 Mon Sep 17 00:00:00 2001
From: Darcy Wong
Date: Wed, 25 Mar 2026 15:40:19 +0700
Subject: [PATCH 02/38] fix: more rewrites involving _content
---
.htaccess | 19 ++++++++++---------
1 file changed, 10 insertions(+), 9 deletions(-)
diff --git a/.htaccess b/.htaccess
index 1d5f1882..1ecd9321 100644
--- a/.htaccess
+++ b/.htaccess
@@ -219,24 +219,25 @@ RewriteRule "^(.+[^/])$" "$1/" [R,END]
# TODO: mdhost currently in a different path than help.keyman
+# TODO: en --> should be a bcp-47 type 'lang' match (e.g. ab[-x][-y]) ignore case, keep it a fairly loose expression [a-z][a-z][a-z]?(-...)?
+
# Rewrite file to file.md
RewriteCond "%{DOCUMENT_ROOT}/_content/$2.md" -f
-# en --> should be a bcp-47 type 'lang' match (e.g. ab[-x][-y]) ignore case, keep it a fairly loose expression [a-z][a-z][a-z]?(-...)?
RewriteRule "^(en)/(.+)$" "/_includes/includes/md/mdhost.php?file=_content/$2.md&lang=$1" [END]
# Rewrite file to file.php
-RewriteCond "%{DOCUMENT_ROOT}/$1.php" -f
-RewriteCond "%{DOCUMENT_ROOT}/$1.md" !-f
-RewriteRule "^(.+)$" "$1.php" [END]
+RewriteCond "%{DOCUMENT_ROOT}/_content/$2.php" -f
+RewriteCond "%{DOCUMENT_ROOT}/_content/$2.md" !-f
+RewriteRule "^(en)/(.+)$" "/_content/$2.php?lang=$1" [END]
# Rewrite folder/ to folder/index.md
-RewriteCond "%{DOCUMENT_ROOT}/$1/index.md" -f
-RewriteRule "^(.+)/$" "/_includes/includes/md/mdhost.php?file=$1/index.md" [END]
+RewriteCond "%{DOCUMENT_ROOT}/_content/$2/index.md" -f
+RewriteRule "^(en)/(.+)/$" "/_includes/includes/md/mdhost.php?file=_content/$2/index.md&lang=$1" [END]
# Rewrite folder/ to folder/index.php
-RewriteCond "%{DOCUMENT_ROOT}/$1/index.php" -f
-RewriteCond "%{DOCUMENT_ROOT}/$1/index.md" !-f
-RewriteRule "^(.+)/$" "$1/index.php" [END]
+RewriteCond "%{DOCUMENT_ROOT}/_content/$2/index.php" -f
+RewriteCond "%{DOCUMENT_ROOT}/_content/$2/index.md" !-f
+RewriteRule "^(en)/(.+)/$" "/_content/$2/index.php?lang=$1" [END]
# Finally, append the terminating slash for folders, given it is no longer
# done automatically because we put DirectorySlash off
From d98b2366236b953f1ee974ddf5c72b81a34514cf Mon Sep 17 00:00:00 2001
From: Darcy Wong
Date: Tue, 31 Mar 2026 06:44:24 +0700
Subject: [PATCH 03/38] fix: Add lang to Head.php
---
_includes/2020/templates/Head.php | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/_includes/2020/templates/Head.php b/_includes/2020/templates/Head.php
index e5c7f134..c01aa379 100644
--- a/_includes/2020/templates/Head.php
+++ b/_includes/2020/templates/Head.php
@@ -31,6 +31,11 @@ static function render($fields = []) {
if(!isset($fields->js)) {
$fields->js = [];
}
+
+ // Fallback to 'en'
+ // TODO-I18N-URL-SCHEME: integrate with Locale.php
+ $fields->lang = isset($_REQUEST['lang']) ? $_REQUEST['lang'] : 'en';
+
?>
language)) {
From f4d6d99730733d4178f4db415940b64b79ff75e1 Mon Sep 17 00:00:00 2001
From: Darcy Wong
Date: Tue, 31 Mar 2026 10:32:38 +0700
Subject: [PATCH 04/38] fix: redirects to currentlang
---
.htaccess | 11 +++++------
_content/developer/index.php | 6 +++---
_content/developer/keymanweb/index.php | 10 +++++-----
_content/downloads/index.php | 2 +-
_content/windows/index.php | 2 +-
5 files changed, 15 insertions(+), 16 deletions(-)
diff --git a/.htaccess b/.htaccess
index 1ecd9321..752a1ee0 100644
--- a/.htaccess
+++ b/.htaccess
@@ -33,9 +33,9 @@ RewriteRule ^crowdin.yml$ = [F,L]
RewriteRule "^.well-known/apple-app-site-association$" "/.well-known/apple-app-site-association.json" [L]
# Rewrite //... ignoring known 2-3 letter folders
-#RewriteCond "$1" !-f
-#RewriteCond "$1" !-d
-#RewriteRule "^/(?!cdn|go|mac|web)/(.+)?/" "/_content/$2?lang=$1"
+RewriteCond "$1" !-f
+RewriteCond "$1" !-d
+RewriteRule "^/(?!cdn|go|mac|web)/(.+)?/" "/_content/$2?lang=$1"
# macosx and macos to mac (ignore case)
RewriteRule "^(macosx|macos)\b(.*)$" "/mac$2" [NC,R=301,END,QSA]
@@ -185,7 +185,6 @@ RedirectMatch "^/(french|german|italian|spanish|swedish)(/?)$" "/keyboards
# dedicated-keyboard-landing pages
RedirectMatch 301 "^/(amharic|burmese|cameroon|ethiopic|eurolatin|greek|ipa|sinhala|tamil|tibetan|tigrigna|urdu)(/.*)?$" "/keyboards/h/$1$2"
-
#
# if $1 is a folder or file in /_content, then redirect to currentlang (en?)
# e.g. would redirect windows/download --> en/windows/download/
@@ -241,7 +240,7 @@ RewriteRule "^(en)/(.+)/$" "/_content/$2/index.php?lang=$1" [END]
# Finally, append the terminating slash for folders, given it is no longer
# done automatically because we put DirectorySlash off
-RewriteCond %{REQUEST_FILENAME} -d
-RewriteRule "^(.*)([^/])$" "$1$2/" [R]
+RewriteCond "%{DOCUMENT_ROOT}/_content/$2$3" -d
+RewriteRule "^(en)(.*)([^/])$" "$1$2$3/" [R,QSA]
diff --git a/_content/developer/index.php b/_content/developer/index.php
index c44079ed..f2cf45be 100644
--- a/_content/developer/index.php
+++ b/_content/developer/index.php
@@ -17,14 +17,14 @@
?>
Keyman Developer
-Keyman Developer is the most powerful tool for creating
+
Keyman Developer is the most powerful tool for creating
keyboard layouts for any popular platform for any language around the world. Build keyboards layouts for desktop,
web, tablet and phone. Optimise your keyboards for each platform, including touch-and-hold keys and alternative layers.
diff --git a/_content/developer/keymanweb/index.php b/_content/developer/keymanweb/index.php
index eb817d20..d165cb72 100644
--- a/_content/developer/keymanweb/index.php
+++ b/_content/developer/keymanweb/index.php
@@ -19,7 +19,7 @@
KeymanWeb Source Code and Development
KeymanWeb = $stable_version; ?> is an Open Source input method system for the web, supporting both desktops and touch devices. Keyboard layouts for
- use with KeymanWeb can be created with the free download Keyman Developer (Windows).
+ use with KeymanWeb can be created with the free download Keyman Developer (Windows).
Add KeymanWeb to a Website
@@ -45,11 +45,11 @@
@@ -97,9 +97,9 @@
diff --git a/_content/downloads/index.php b/_content/downloads/index.php
index d50cb2d8..09c4ea09 100644
--- a/_content/downloads/index.php
+++ b/_content/downloads/index.php
@@ -29,5 +29,5 @@
diff --git a/_content/windows/index.php b/_content/windows/index.php
index f7a120bd..54d452ee 100644
--- a/_content/windows/index.php
+++ b/_content/windows/index.php
@@ -10,7 +10,7 @@
'showMenu' => true,
'banner' => [
'title' => 'Keyman '.$stable_version.' for Windows
Type in your language',
- 'button' => '',
+ 'button' => '',
'image' => 'screenshots/14/windows/osk-malayalam-566x226.png',
'background' => 'water'
]
From 91d69b59f6cf9c9dd37682627e152b666bba5bf7 Mon Sep 17 00:00:00 2001
From: Darcy Wong
Date: Tue, 31 Mar 2026 14:26:12 +0700
Subject: [PATCH 05/38] fix: remove .php from links
---
.htaccess | 3 ++
_content/archive/.htaccess | 3 --
_content/keyboards/h/tigrigna/index.php | 4 +--
_content/linux/index.php | 4 +--
_content/mac/index.php | 4 +--
_content/windows/index.php | 38 +++++++++++------------
_includes/includes/developer-features.php | 2 +-
7 files changed, 29 insertions(+), 29 deletions(-)
delete mode 100644 _content/archive/.htaccess
diff --git a/.htaccess b/.htaccess
index 752a1ee0..7e7887ac 100644
--- a/.htaccess
+++ b/.htaccess
@@ -32,6 +32,9 @@ RewriteRule ^crowdin.yml$ = [F,L]
# apple-app-site-association
RewriteRule "^.well-known/apple-app-site-association$" "/.well-known/apple-app-site-association.json" [L]
+# Redirect /archive/downloads.php"
+RewriteRule "^(archive)/(downloads)(\.php)?$" "en/$2/$1/" [NC,R=301,QSA]
+
# Rewrite //... ignoring known 2-3 letter folders
RewriteCond "$1" !-f
RewriteCond "$1" !-d
diff --git a/_content/archive/.htaccess b/_content/archive/.htaccess
deleted file mode 100644
index 0599591b..00000000
--- a/_content/archive/.htaccess
+++ /dev/null
@@ -1,3 +0,0 @@
-
-# Redirect /archive/downloads.php"
-RedirectMatch 301 "/archive/downloads.php" "/downloads/archive/"
diff --git a/_content/keyboards/h/tigrigna/index.php b/_content/keyboards/h/tigrigna/index.php
index a11b8b32..4f6838d5 100644
--- a/_content/keyboards/h/tigrigna/index.php
+++ b/_content/keyboards/h/tigrigna/index.php
@@ -16,7 +16,7 @@
Type in Tigrigna on iPhone, iPad, Windows, macOS, Linux, and Android. Our Tigrigna keyboards works with Microsoft Word, Photoshop, Facebook, Twitter, email and thousands of other applications.
- Click here for Tigirigna (Eritrea)
+ Click here for Tigirigna (Eritrea)
@@ -115,7 +115,7 @@
Type in other Ethiopic languages such as:
- - Tigrigna (Eritrea)
+ - Tigrigna (Eritrea)
- Awngi & Xamtanga
- Blin
- Ge'ez
diff --git a/_content/linux/index.php b/_content/linux/index.php
index 72403827..af758e9d 100644
--- a/_content/linux/index.php
+++ b/_content/linux/index.php
@@ -12,7 +12,7 @@
'showMenu' => true,
'banner' => [
'title' => 'Keyman for Linux
Type in your language',
- 'button' => '',
+ 'button' => '',
'image' => 'linux-osk-khmer.png',
'background' => 'water'
]
@@ -34,7 +34,7 @@
* Keyman Developer is currently a Windows-only product; however, the command line compiler kmcomp runs in WINE.
-
+
true,
'banner' => [
'title' => 'Keyman for macOS
Type in your language',
- 'button' => '',
+ 'button' => '',
'image' => 'mac-osk-hebrew.png',
'background' => 'water'
]
@@ -31,7 +31,7 @@
Adobe Creative Suite, internet browsers and more, as well as supporting the latest version of macOS.
-
+
@@ -47,7 +42,7 @@ static function render(array $fields = []) {
@@ -65,8 +60,8 @@ static function render(array $fields = []) {
diff --git a/_includes/2020/templates/Head.php b/_includes/2020/templates/Head.php
index c01aa379..c9218cac 100644
--- a/_includes/2020/templates/Head.php
+++ b/_includes/2020/templates/Head.php
@@ -32,10 +32,6 @@ static function render($fields = []) {
$fields->js = [];
}
- // Fallback to 'en'
- // TODO-I18N-URL-SCHEME: integrate with Locale.php
- $fields->lang = isset($_REQUEST['lang']) ? $_REQUEST['lang'] : 'en';
-
?>
language)) {
diff --git a/_includes/2020/templates/Menu.php b/_includes/2020/templates/Menu.php
index 417be7e3..4a9a197b 100644
--- a/_includes/2020/templates/Menu.php
+++ b/_includes/2020/templates/Menu.php
@@ -21,10 +21,6 @@ public static function render(array $fields): void {
$fields->stable_version = KeymanVersion::stable_version;
$fields->beta_version = KeymanVersion::beta_version;
- // Fallback to 'en'
- // TODO-I18N-URL-SCHEME: integrate with Locale.php
- $fields->lang = isset($_REQUEST['lang']) ? $_REQUEST['lang'] : 'en';
-
echo <<
END;
@@ -132,7 +128,7 @@ private static function render_phone_menu(object $fields): void {