Persian Origins Plugin
The plugin’s focus will be: - EN/Persian language switcher - Story mode navigation (next/prev in same category) - User reading progress (resume later)
by Persian Origins · github.com/arash12javadi/persian-origins · website
Install
No release zip yet. The repository archive installs, but the folder name will carry the branch suffix and updates will not flow:
wp plugin install https://github.com/arash12javadi/persian-origins/archive/refs/heads/Plugin.zipReadme
Persian Origins Plugin
Provides a bilingual front-end experience for PersianOrigins.com: language switching (EN/FA), per-language font selection, theme (light/dark), content direction (LTR/RTL) scoping, reading progress, story navigation, and a small cookie notice.
The plugin is built to be theme-agnostic, a11y-friendly, and performant (no heavy frameworks, lazy CSS, font-display: swap).
Shortcodes Documentation
The plugin registers three shortcodes for bilingual content management.
[language_switch]
Renders the language switcher UI with flag icons and toggle functionality.
Syntax
[language_switch mode="inline" class="" link_class="" outer_class=""]
Attributes
| Attribute | Type | Default | Description |
|---|---|---|---|
mode |
string | inline |
Display mode: inline or floating |
class |
string | '' |
Additional CSS classes for the inner wrapper |
link_class |
string | '' |
CSS classes for the language link elements |
outer_class |
string | Auto | CSS classes for the outer wrapper (auto-generated if empty) |
Examples
Basic usage:
[language_switch]
Floating mode:
[language_switch mode="floating"]
With custom classes:
[language_switch class="my-custom-class" link_class="custom-link"]
With outer wrapper class:
[language_switch outer_class="my-wrapper-class"]
Notes
- Respects current language context
- Swaps flag images in DOM order for consistent stacking
- Links to opposite language page or safe fallback
- Works in pages, posts, and shortcode-enabled widgets
- Styled by plugin's global CSS
- Auto-assigns wrapper classes based on mode if
outer_classis empty
[continue_reading]
Displays a "Continue Reading" button that directs users to the next unread post in a category.
Syntax
[continue_reading category="" class=""]
Attributes
| Attribute | Type | Default | Description |
|---|---|---|---|
category |
string/int | Required | Category slug or ID |
class |
string | '' |
Additional CSS classes for the button |
Examples
With category slug:
[continue_reading category="tutorials"]
With category ID:
[continue_reading category="42"]
With custom styling:
[continue_reading category="guides" class="btn-primary btn-lg"]
Behavior
- Tracks read posts via localStorage with cookie fallback
- Returns empty string if category parameter is missing or invalid
- Accepts both category slug and numeric ID
- Calculates next unread post within specified category
- Reading progress is per-browser (not server-side)
- May point to first post if all posts are read
[po_categories]
Renders a responsive grid of categories with bilingual titles, descriptions, and optional images.
Syntax
[po_categories taxonomy="category" include="" exclude="" hide_empty="false"
number="" orderby="name" order="ASC" columns="3"
image_size="medium" parent=""]
Attributes
| Attribute | Type | Default | Description |
|---|---|---|---|
taxonomy |
string | category |
Taxonomy to query |
include |
string | '' |
Comma-separated term IDs to include |
exclude |
string | '' |
Comma-separated term IDs to exclude |
hide_empty |
string | false |
Whether to hide categories with no posts |
number |
int | '' |
Maximum number of categories to display |
orderby |
string | name |
Sort field (name, count, slug, etc.) |
order |
string | ASC |
Sort order: ASC or DESC |
columns |
int | 3 |
Number of grid columns (1-6) |
image_size |
string | medium |
WordPress image size slug |
parent |
int | '' |
Parent term ID (use 0 for top-level only) |
Examples
Default 3-column grid:
[po_categories]
4 columns with 12 items:
[po_categories columns="4" number="12"]
Specific categories with thumbnails:
[po_categories include="5,12,18" image_size="thumbnail"]
Top-level categories by post count:
[po_categories parent="0" orderby="count" order="DESC"]
Include specific categories:
[po_categories include="3,7,15,22"]
Exclude specific categories:
[po_categories exclude="1,9"]
Custom taxonomy:
[po_categories taxonomy="custom_tax" columns="2"]
Output Structure
Each category card displays:
- Optional featured image (if set via category meta)
- Bilingual title (English from core, Persian from meta with fallback)
- Bilingual description (English from core, Persian from meta with fallback)
- Automatic language toggling via body classes (
po-lang-en/po-lang-fa)
Bilingual Behavior
- English content uses standard WordPress category fields
- Persian content uses custom meta fields:
po_cat_name_fafor Persian titlepo_cat_desc_fafor Persian descriptionpo_cat_img_idfor featured image
- Falls back to English if Persian content is missing
- Language visibility controlled by body class CSS
Styling
The shortcode includes minimal built-in CSS for:
- Responsive grid layout (1-6 columns)
- Card structure and spacing
- Language-specific content visibility
- Customize appearance using CSS variables:
--po-card-bg(default:#f7f7f7)--po-border(default:#e5e5e5)--po-muted(default:#555)
Notes
- Returns empty string if no categories found
- Images are lazy-loaded for performance
- All category names and descriptions are properly escaped
- Links point to category archive pages
- Respects WordPress taxonomy hierarchy
[site_settings]
Renders a site settings panel with controls for theme, fonts, and text size preferences.
Syntax
[site_settings class="" mode="full"]
Attributes
| Attribute | Type | Default | Description |
|---|---|---|---|
class |
string | '' |
Additional CSS classes for the wrapper |
mode |
string | full |
Display mode: full (with toggle button) or panel (always visible) |
Examples
Basic usage (with toggle button):
[site_settings]
Always visible panel:
[site_settings mode="panel"]
With custom class:
[site_settings class="my-custom-settings"]
Panel-only mode with class:
[site_settings mode="panel" class="sidebar-settings"]
Features
The site settings panel includes three control sections:
1. Theme Selector
- Toggle between light and dark themes
- Preference saved in cookies (
po_site_theme) - Applies
.po-theme-lightor.po-theme-darkbody class
2. Font Selector
- Separate font controls for English and Persian
- Shows/hides based on current language context
- Options include:
- System default
- Custom fonts loaded from plugin's
assets/fonts/directory
- Supports multiple font weights and styles (regular, bold, italic)
- Preferences saved in cookies (
po_font_en,po_font_fa) - Applies language-specific font classes to body
3. Text Size Controls
- Increase text size (A+)
- Decrease text size (A−)
- Reset to default (Reset button)
- Live output display showing current percentage
- Accessible controls with ARIA labels
Display Modes
Full Mode (default):
- Includes a toggle button with gear icon (⚙)
- Panel is initially hidden
- Click button to show/hide settings
- Ideal for header/sidebar integration
Panel Mode:
- No toggle button
- Panel is always visible
- Useful for dedicated settings pages
- Suitable for embedding in page content
Technical Details
Font System:
- Automatically loads fonts from
/assets/fonts/en/and/assets/fonts/fa/ - Supports WOFF and WOFF2 formats
- Generates
@font-facedeclarations dynamically - Font weights detected from filenames (thin, light, regular, medium, bold, etc.)
- Font styles detected from filenames (italic detection)
Cookie Storage:
- Theme:
po_site_theme(values:light,dark) - English font:
po_font_en(value: font slug orsystem) - Persian font:
po_font_fa(value: font slug orsystem) - Cookie expiration: 1 year
Body Classes Applied:
- Theme:
.po-theme-lightor.po-theme-dark - Language:
.po-lang-enor.po-lang-fa - Direction:
.po-dir-ltror.po-dir-rtl - Font:
.po-font-{language}-{slug}(e.g.,.po-font-en-open-sans)
Accessibility:
- Proper ARIA labels and attributes
- Keyboard accessible controls
- Live regions for dynamic updates
- Semantic HTML structure
Integration Notes
- A floating version is automatically rendered in
wp_footer(priority 20) - Shortcode version adds
.po-site-settings--shortcodeclass - Panel-only mode adds
.po-site-settings--panel-onlyclass - Each instance has a unique ID to prevent conflicts
- Works seamlessly with the language switcher
- Font changes apply immediately via body classes
- Theme changes trigger instant visual updates
Styling
The component uses CSS variables for easy customization:
- Custom styling can target
.po-site-settingswrapper - Panel styles use
.po-site-settings__panel - Button styles use
.po-site-settings__btn - Select dropdowns use
.po-site-settings__select
Example Use Cases
In a sidebar widget:
[site_settings mode="panel" class="widget-settings"]
In page content with toggle:
[site_settings class="content-settings"]
Dedicated settings page:
[site_settings mode="panel"]
Bilingual Content
- English: Uses term's native
nameanddescription - Persian: Pulls from custom term meta (
name_fa,desc_fa) with EN fallback - Language visibility: Controlled by body classes
body.po-lang-en .po-text--fa { display:none }body.po-lang-fa .po-text--en { display:none }
Images
- Retrieves featured image from term meta
- Uses
wp_get_attachment_image()with specified size - Falls back gracefully if no image exists
Styling
CSS Classes Available
Language Switch:
.po-language-switch- Root wrapper- Custom classes via
classandlink_classattributes
Continue Reading:
.po-continue-reading- Button wrapper- Custom classes via
classattribute
Categories Grid:
.po-cat-grid- Grid container.po-cat-grid.cols-N- Column variants (N = 1-6).po-cat-card- Individual card.po-cat-card__media- Image wrapper.po-cat-card__body- Content wrapper.po-cat-title- Title heading.po-cat-desc- Description wrapper.po-text--en- English text.po-text--fa- Persian text
Best Practices
- Sanitization: All attributes are sanitized automatically
- Invalid Input: Returns empty string instead of errors
- Custom CSS: Add theme overrides after plugin styles
- Class Attributes: Use space-separated valid class names
- Language Toggle: Both languages render; body class controls visibility
Common Use Cases
Sidebar language switcher:
[language_switch class="sidebar-widget"]
Category archive with continue reading:
[po_categories category="articles" columns="3"]
[continue_reading category="articles" class="mt-4"]
Featured categories homepage:
[po_categories include="5,7,9,12" columns="4" image_size="large" hide_empty="true"]
Tag cloud alternative:
[po_categories taxonomy="post_tag" orderby="count" order="DESC" number="20" columns="5"]
Features
Language switcher (EN ⇄ FA)
- Front-end floating switch with a compact flag tab that slides a panel in from the left.
- Keeps its position fixed on the left for both LTR/RTL.
- Redirects to the matching translation (if available) or safely falls back.
- Persists user preference in cookie/user meta.
- Adds semantic classes to
<body>(e.g.po-lang-fa,po-dir-rtl).
Per-language fonts (dynamic @font-face)
- Auto-discovers fonts in
assets/fonts/en/*andassets/fonts/fa/*(WOFF/WOFF2). - Detects weight/style from filename (e.g. Bold, Italic).
- Generates
@font-face+ rules on the fly; applies via:body.po-lang-<lang>.po-font-<lang>-<slug>article[data-font-<lang>="<slug>"](fine-grained & previews)
- Per-language font selection UI inside the Site Settings panel.
- Cookies:
po_font_en,po_font_fa.
Theme switch (light/dark)
- Respects system preference, persists theme (
localStorage+ cookiepo_theme). - Applies early to prevent FOUC, mirrors on
<body>aspo-theme-<light|dark>and on articles viadata-theme.
Direction control (RTL/LTR)
- Only flips post content to RTL when Persian is active (
po-dir-rtlon body). - Keeps UI widgets (language switch, settings panel) LTR to avoid mirrored UX.
Reading progress & story navigation
- Tracks read posts per category (via
localStorage+ cookie), draws simple progress bars. - A "previous/next" story navigation component with mirrored layout for FA.
Cookie popup
- Small, theme-neutral cookie notice (class included & registered).
A11y & UX niceties
- Focus rings, ESC to close settings, click-outside to dismiss, ARIA labels, keyboard-navigable toggle.
Read the full README on GitHub →
Releases
These releases are tags only. The author does not attach a packaged zip, so there are no download counts to report.