Grammatical gender is one of the most complex challenges in internationalization. Unlike English, which uses gender primarily for pronouns, many languages assign grammatical gender to all nouns and require agreement across adjectives, articles, and verb forms. This guide covers everything developers need to know about handling gender in i18n, from Romance and Slavic systems to gender-neutral strategies.
Understanding Grammatical Gender Systems
Grammatical gender is a linguistic feature where nouns are classified into categories (masculine, feminine, neuter, or others) that affect surrounding words. This classification is often arbitrary and unrelated to biological gender.
Two-Gender Systems (Romance Languages)
Languages like Spanish, French, Italian, and Portuguese use masculine and feminine genders:
Spanish Example:
- "El usuario está conectado" (The user [masc] is connected [masc])
- "La usuaria está conectada" (The user [fem] is connected [fem])
French Example:
- "Le développeur est expérimenté" (The developer [masc] is experienced [masc])
- "La développeuse est expérimentée" (The developer [fem] is experienced [fem])
Three-Gender Systems (Slavic Languages)
Russian, Polish, Czech, and other Slavic languages add neuter gender:
Russian Example:
- "Пользователь (masc) подключён (masc)" (User is connected)
- "Пользовательница (fem) подключена (fem)" (User is connected)
- "Подключение (neut) завершено (neut)" (Connection is completed)
Complex Gender Systems (Arabic)
Arabic has masculine and feminine, but with additional complexity:
- Dual forms for exactly two items
- Broken plurals with unpredictable gender
- Different agreement rules for human vs. non-human plurals
Arabic Example:
- "المستخدم متصل" (The user [masc] connected [masc])
- "المستخدمة متصلة" (The user [fem] connected [fem])
- "المستخدمون متصلون" (The users [masc pl] connected [masc pl])
- "المستخدمات متصلات" (The users [fem pl] connected [fem pl])
The ICU MessageFormat Select Solution
The Industry's standard solution for grammatical gender is the ICU MessageFormat select format, which allows conditional text based on a variable value.
Basic Select Syntax
JavaScript1const message = "{gender, select, " + 2 "male {He is connected} " + 3 "female {She is connected} " + 4 "other {They are connected}" + 5"}"; 6 7// Usage 8formatMessage(message, { gender: 'female' }); 9// Output: "She is connected"
Multi-Level Agreement
Real-world applications often require multiple agreements in a single sentence:
JavaScript1// Spanish: Agreement on article, noun, adjective, and participle 2const welcomeMessage = "{gender, select, " + 3 "male {Bienvenido al sistema. Tu cuenta ha sido activada.} " + 4 "female {Bienvenida al sistema. Tu cuenta ha sido activada.} " + 5 "other {Bienvenido/a al sistema. Tu cuenta ha sido activada.}" + 6"}";
Nested Select for Complex Scenarios
JavaScript1// French: Different agreement for singular vs plural 2const statusMessage = "{count, plural, " + 3 "one {{gender, select, " + 4 "male {L'utilisateur est connecté} " + 5 "female {L'utilisatrice est connectée} " + 6 "other {L'utilisateur·rice est connecté·e}" + 7 "}} " + 8 "other {{gender, select, " + 9 "male {Les utilisateurs sont connectés} " + 10 "female {Les utilisatrices sont connectées} " + 11 "other {Les utilisateur·rice·s sont connecté·e·s}" + 12 "}}" + 13"}";
Implementation Patterns
Storing User Gender Preference
TypeScript1interface UserProfile { 2 id: string; 3 displayName: string; 4 preferredLanguage: string; 5 // Gender for grammatical agreement only 6 grammaticalGender?: 'male' | 'female' | 'neutral' | 'unspecified'; 7} 8 9// Database schema 10CREATE TABLE user_profiles ( 11 id UUID PRIMARY KEY, 12 display_name TEXT NOT NULL, 13 preferred_language TEXT NOT NULL, 14 grammatical_gender TEXT CHECK ( 15 grammatical_gender IN ('male', 'female', 'neutral', 'unspecified') 16 ), 17 created_at TIMESTAMP DEFAULT NOW() 18);
React Implementation
TypeScript1import { useIntl } from 'react-intl'; 2 3interface WelcomeProps { 4 user: UserProfile; 5} 6 7function WelcomeMessage({ user }: WelcomeProps) { 8 const intl = useIntl(); 9 10 const message = intl.formatMessage( 11 { id: 'welcome.greeting' }, 12 { 13 gender: user.grammaticalGender || 'other', 14 name: user.displayName 15 } 16 ); 17 18 return <h1>{message}</h1>; 19} 20 21// Translation file (en.json) 22{ 23 "welcome.greeting": "{name}, you are connected" 24} 25 26// Translation file (es.json) 27{ 28 "welcome.greeting": "{gender, select, male {{name}, estás conectado} female {{name}, estás conectada} other {{name}, estás conectado/a}}" 29}
Backend API Design
GO1// Go backend example 2type UserPreferences struct { 3 LanguageCode string `json:"language_code"` 4 GrammaticalGender *string `json:"grammatical_gender,omitempty"` 5} 6 7func (h *Handler) GetLocalizedMessage(w http.ResponseWriter, r *http.Request) { 8 user := getUserFromContext(r.Context()) 9 10 params := map[string]interface{}{ 11 "gender": getGenderOrDefault(user.Preferences.GrammaticalGender), 12 "name": user.DisplayName, 13 } 14 15 message := h.i18n.Localize(user.Preferences.LanguageCode, "welcome.greeting", params) 16 17 json.NewEncoder(w).Write(map[string]string{ 18 "message": message, 19 }) 20} 21 22func getGenderOrDefault(gender *string) string { 23 if gender == nil { 24 return "other" 25 } 26 return *gender 27}
Gender-Neutral Strategies
Many applications are moving toward gender-neutral language to be more inclusive and to simplify localization.
English Gender-Neutral Patterns
JavaScript1// Instead of: "He/She is connected" 2// Use: "You are connected" (second person) 3// Use: "Connected" (status without subject) 4// Use: "This user is connected" (demonstrative + noun) 5// Use: "They are connected" (singular they)
Romance Language Strategies
1. Inclusive Morphemes (Spanish/French):
Spanish: "Bienvenido/a" or "Bienvenid@" or "Bienvenidx"
French: "Bienvenu·e" or "Bienvenu.e"
2. Collective Nouns:
Instead of: "Los usuarios" (the users [masc])
Use: "Las personas usuarias" (the user persons [fem collective])
3. Passive Voice:
Instead of: "El usuario ha sido conectado" (requires gender)
Use: "La conexión ha sido establecida" (connection established, no gender)
German Gender-Neutral Solutions
Traditional: "Benutzer" (masc) / "Benutzerin" (fem)
Gender-neutral: "Benutzende" (using participle form)
Inclusive: "Benutzer*in" or "Benutzer:in" or "Benutzer_in"
Slavic Language Challenges
Slavic languages have fewer gender-neutral options due to extensive agreement:
JavaScript1// Russian: Limited options, often requires explicit selection 2const russianMessage = "{gender, select, " + 3 "male {Вы подключены} " + // You [masc] are connected 4 "female {Вы подключены} " + // You [fem] are connected 5 "other {Вы подключены}" + // Plural form (neutral) 6"}";
Avoiding Gender Assumptions in UI
Profile Setup Best Practices
TypeScript1// Good: Optional gender field with clear purpose 2interface ProfileForm { 3 displayName: string; 4 email: string; 5 // Optional: Only for grammatical purposes 6 grammaticalGender?: { 7 value: 'male' | 'female' | 'neutral' | 'unspecified'; 8 label: string; // Explain why you're asking 9 }; 10} 11 12// UI Component 13function GenderField() { 14 return ( 15 <fieldset> 16 <legend> 17 Grammatical Gender (Optional) 18 <Tooltip> 19 Used only to display messages correctly in your language. 20 This does not affect your identity or profile visibility. 21 </Tooltip> 22 </legend> 23 24 <label> 25 <input type="radio" name="gender" value="male" /> 26 Masculine forms 27 </label> 28 29 <label> 30 <input type="radio" name="gender" value="female" /> 31 Feminine forms 32 </label> 33 34 <label> 35 <input type="radio" name="gender" value="neutral" /> 36 Neutral/inclusive forms 37 </label> 38 39 <label> 40 <input type="radio" name="gender" value="unspecified" checked /> 41 No preference 42 </label> 43 </fieldset> 44 ); 45}
Default to Neutral Language
JavaScript1// Translation keys should default to neutral forms 2{ 3 // Bad: Assumes gender 4 "profile.greeting": "Welcome back, {name}! You are logged in.", 5 6 // Good: Gender-neutral by default 7 "profile.greeting": "Welcome back, {name}! Your session is active.", 8 9 // If gender is needed, make it explicit 10 "profile.greeting_gendered": "{gender, select, male {Welcome back, {name}! You are logged in.} female {Welcome back, {name}! You are logged in.} other {Welcome back, {name}! Your session is active.}}" 11}
Testing Gender Agreements
TypeScript1import { render, screen } from '@testing-library/react'; 2import { IntlProvider } from 'react-intl'; 3 4describe('Gender Agreement Tests', () => { 5 it('should display correct Spanish gender agreement (masculine)', () => { 6 const messages = { 7 'welcome.message': '{gender, select, male {Bienvenido} female {Bienvenida} other {Bienvenido/a}}' 8 }; 9 10 render( 11 <IntlProvider locale="es" messages={messages}> 12 <WelcomeMessage user={{ grammaticalGender: 'male' }} /> 13 </IntlProvider> 14 ); 15 16 expect(screen.getByText(/Bienvenido$/)).toBeInTheDocument(); 17 }); 18 19 it('should display correct Spanish gender agreement (feminine)', () => { 20 const messages = { 21 'welcome.message': '{gender, select, male {Bienvenido} female {Bienvenida} other {Bienvenido/a}}' 22 }; 23 24 render( 25 <IntlProvider locale="es" messages={messages}> 26 <WelcomeMessage user={{ grammaticalGender: 'female' }} /> 27 </IntlProvider> 28 ); 29 30 expect(screen.getByText(/Bienvenida$/)).toBeInTheDocument(); 31 }); 32 33 it('should handle unspecified gender with neutral form', () => { 34 const messages = { 35 'welcome.message': '{gender, select, male {Bienvenido} female {Bienvenida} other {Bienvenido/a}}' 36 }; 37 38 render( 39 <IntlProvider locale="es" messages={messages}> 40 <WelcomeMessage user={{ grammaticalGender: undefined }} /> 41 </IntlProvider> 42 ); 43 44 expect(screen.getByText(/Bienvenido/a$/)).toBeInTheDocument(); 45 }); 46});
IntlPull's Gender Handling Features
IntlPull provides specialized support for grammatical gender management:
1. ICU MessageFormat Support
All ICU select formats are fully supported with visual preview:
JavaScript1// IntlPull editor shows live preview for each variant 2{ 3 "user.status": "{gender, select, male {Connected} female {Connected} other {Connected}}" 4}
2. Gender Variant Testing
IntlPull's translation interface allows testers to preview all gender variants:
- Switch between male/female/other variants instantly
- See all agreements in context
- Flag inconsistencies across related keys
3. Translation Memory with Gender Context
IntlPull's TM system understands gender context:
Source: "You are connected"
Spanish (male): "Estás conectado"
Spanish (female): "Estás conectada"
Spanish (neutral): "Estás conectado/a"
// TM suggests appropriate variant based on gender parameter
4. Validation Rules
Set validation rules to ensure gender agreements:
YAML1validation: 2 - rule: gender_consistency 3 description: "All gender variants must be present" 4 applies_to: ["es", "fr", "de", "ru"] 5 severity: error
Real-World Implementation Examples
Example 1: Notification System
TypeScript1// Notification with multiple gender agreements 2const notificationMessages = { 3 en: { 4 'notification.comment': '{commenterName} commented on your post' 5 }, 6 es: { 7 'notification.comment': '{gender, select, ' + 8 'male {{commenterName} comentó en tu publicación} ' + 9 'female {{commenterName} comentó en tu publicación} ' + 10 'other {{commenterName} comentó en tu publicación}' + 11 '}' 12 }, 13 fr: { 14 'notification.comment': '{gender, select, ' + 15 'male {{commenterName} a commenté votre publication} ' + 16 'female {{commenterName} a commenté votre publication} ' + 17 'other {{commenterName} a commenté votre publication}' + 18 '}' 19 } 20}; 21 22// Usage 23function sendNotification(recipient: User, commenter: User) { 24 const message = formatMessage( 25 'notification.comment', 26 { 27 commenterName: commenter.displayName, 28 gender: commenter.grammaticalGender || 'other' 29 }, 30 recipient.preferredLanguage 31 ); 32 33 // Send notification 34}
Example 2: Email Templates
TypeScript1// Email subject with gender agreement 2const emailSubjects = { 3 en: { 4 'email.welcome.subject': 'Welcome to our platform, {name}!' 5 }, 6 de: { 7 'email.welcome.subject': '{gender, select, ' + 8 'male {Willkommen auf unserer Plattform, {name}!} ' + 9 'female {Willkommen auf unserer Plattform, {name}!} ' + 10 'other {Willkommen auf unserer Plattform, {name}!}' + 11 '}' 12 } 13}; 14 15// Email body with multiple agreements 16const emailBodies = { 17 de: { 18 'email.welcome.body': '{gender, select, ' + 19 'male {Lieber {name}, 20 21Sie wurden als Benutzer registriert.} ' + 22 'female {Liebe {name}, 23 24Sie wurden als Benutzerin registriert.} ' + 25 'other {Hallo {name}, 26 27Sie wurden registriert.}' + 28 '}' 29 } 30};
Example 3: Status Messages
TypeScript1// Status display with agreement 2const statusMessages = { 3 ru: { 4 'status.online': '{gender, select, ' + 5 'male {Вы онлайн} ' + 6 'female {Вы онлайн} ' + 7 'other {Вы онлайн}' + 8 '}', 9 'status.verified': '{gender, select, ' + 10 'male {Вы подтверждены} ' + 11 'female {Вы подтверждены} ' + 12 'other {Вы подтверждены}' + 13 '}' 14 } 15};
Frequently Asked Questions
Q: Should I ask users for their gender?
Only if necessary for grammatical purposes in languages with gender agreement. Always make it optional, explain why you're asking, and provide neutral options. Many apps avoid this entirely by using gender-neutral language patterns.
Q: What's the difference between grammatical gender and gender identity?
Grammatical gender is a linguistic feature for proper sentence construction. Gender identity is personal identity. They may not align. Always clarify you're asking about language preference, not identity.
Q: How do I handle gender in languages I don't speak?
Use ICU MessageFormat select and work with native speakers or professional translators. Don't guess gender agreements—they're complex and errors are noticeable to native speakers.
Q: Can I use machine translation for gender variants?
Machine translation often struggles with gender agreement across entire sentences. Use it for drafts only, then have native speakers review all variants.
Q: What if a language has no gender?
Languages like Turkish, Finnish, Hungarian, and Chinese don't have grammatical gender. Your ICU select messages will simply return the same text for all variants, which is fine—the overhead is minimal.
Q: How do I test gender agreement bugs?
Create test users with different grammatical gender preferences. Test all UI strings that reference the user. Use automated tests to verify each variant renders correctly.
Q: Should I support more than male/female/other?
For grammatical purposes, most languages have 2-3 genders. Supporting other as a neutral fallback covers inclusive cases. Don't create gender categories beyond what the language requires grammatically.
Q: How does IntlPull help with gender agreement?
IntlPull provides ICU MessageFormat support, variant preview, translation memory with gender context, and validation rules to ensure all gender variants are complete and consistent.
Conclusion
Handling grammatical gender in i18n requires understanding linguistic systems, using ICU MessageFormat select, and implementing inclusive patterns. Key takeaways:
- Use ICU select for languages with grammatical gender
- Make gender preference optional and explain its purpose
- Default to gender-neutral language when possible
- Test all variants with native speakers
- Validate consistency across related strings
Tools like IntlPull simplify gender management with built-in ICU support, variant testing, and validation rules—helping you build inclusive, grammatically correct multilingual applications.
