WinCC Unified Script Login: Force User Language After Login

David Krause17 min read
SiemensTroubleshootingWinCC
Licensed PE Working through this on a live machine? A Maine-licensed engineer can take it from here — included with IMD hardware, by the hour for everything else. Book an engineer

Problem Statement

WinCC Unified Runtime, when authenticating a user via a script call to HMIRuntime.Logon() or through any custom JavaScript that performs a user change, resets the active Runtime language to the language stored in the user object. If the user object does not carry an explicit language, the Runtime falls back to LCID 1033 (en-US, English). Projects that rely on Dutch (LCID 1043), German (LCID 1031), French (LCID 1036), Italian (LCID 1040), Spanish (LCID 1034), Polish (LCID 1045), Czech (LCID 1029), Chinese Simplified (LCID 2052), or any other configured Runtime language experience an immediate and unwanted switch to English after every script-driven login.

The behaviour is reproducible on WinCC Unified V17, V18, and V19 Runtime running on Unified Comfort Panels, Unified Panels with the Unified firmware, and Unified PC Runtime (TIA Portal V17/V18/V19, build 4202.0 and later). The Trace Viewer records the change with the following entry:

trace: User Change for client DESKTOP-7O46EBE succeeded. User: Operator | Language: 1033

The "1033" is the LCID (Locale Identifier, Windows-standard) pushed into the Runtime language controller, overriding the project default configured under Project tree > Runtime settings > Languages & fonts in TIA Portal. The change is committed even when the operator has just manually selected a different language, because the user change event is fired synchronously from HMIRuntime.Logon() and runs after the operator's screen interaction.

The behaviour is documented in section 4.2 of the WinCC Unified V19 system manual, which describes the @UserName tag, the HMIRuntime.Language property, and the recommended workflow for restoring the language after a user change.

Symptoms & Diagnostic Trace

The following symptoms confirm the issue:

  • The HMI screen text reverts to English immediately after a successful script-driven login.
  • The @Language system tag reads 1033 immediately after the logon call, even when the project default is 1043 (Dutch).
  • The on-screen language selector (if present) is bypassed and reverts to "English" or to the language bound to the user object.
  • All multilingual text library (MLT) entries render in English until the operator manually picks a language from the language selector.
  • Single Sign-On (SSO) scenarios that script the logon trigger the same switch on every authentication.
  • Logging on via the standard user view (manual password entry) does not trigger the switch, because the user object's language is honoured and that user was created with the correct locale.

Diagnostic trace output (in HMI RT trace viewer or in the WinCC Unified diagnostic page):

[RT] User Change for client DESKTOP-7O46EBE succeeded. User: Operator | Language: 1033
[RT] @UserName: Operator
[RT] @Language: 1033
[RT] MLT fallback applied for screen: Screen_1

The second line is critical: @Language: 1033 confirms the Runtime language controller has been overwritten by the user object's HmiLanguageId. From this point on, every read of HMIRuntime.Language returns 1033 until the user logs off or a script restores the correct LCID.

Root Cause Analysis

The WinCC Unified user administration is language-aware. Every user record in the TIA Portal user administration (under Security > Users and Roles) carries a HmiLanguageId property. When HMIRuntime.Logon() completes, the Runtime language controller subscribes to the user object. The controller then writes the user object's HmiLanguageId into:

  • HMIRuntime.Language (the active Runtime locale)
  • The @Language system tag
  • The internal MLT (Multilingual Text) resolver used by every Text field, button caption, message class, alarm text, and faceplate caption

If the user was created with the User language set to the project default, the value is correct. However, the following scenarios force the controller to pick up LCID 1033:

  1. User created in a different project that defaulted to English, then exported as a UAD (User Administration Data) fragment and imported. The HmiLanguageId field is preserved as 1033.
  2. User added via the WinCC Unified Openness API (C#/VB.NET) with a User object that did not set the Language property. The constructor initialises it to 1033 by default.
  3. User created before TIA Portal V18, whose HmiLanguageId property was back-filled as 1033 by the migration tool. Pre-V18 users did not carry the property.
  4. User imported from a CSV or scripted import that omitted the language column. The import sets HmiLanguageId to 0 (undefined), which the controller maps to 1033.
  5. Local operator (built-in) account used for first login. The local Operator user has no language configured, so the controller uses the WinCC Unified default fallback (1033).

Additionally, the HMI client itself reports a preferred language to the Runtime based on the client OS display language. When the user change event runs before the client preference is read (which is the case for synchronous script logon), the 1033 default wins.

The project default language, set under Project tree > Runtime settings > Languages & fonts > Reference language, is only consulted when the user object carries no language (HmiLanguageId = 0). Once HmiLanguageId has any non-zero value, the project default is bypassed.

Affected Versions & Configuration

TIA Portal Version WinCC Unified Version Unified Panel Firmware Behaviour Fix Status
V16 Update 6 + HF7 V16 Update 6 V16.0.0.7+ Reproducible Workaround required
V17 Update 5 V17 Update 5 V17.0.0.5 Reproducible Workaround required
V17 Update 6 V17 Update 6 V17.0.0.6 Reproducible Workaround required
V18 Update 2 + HF1 V18 Update 2 V18.0.0.2 Reproducible Workaround required
V18 Update 3 V18 Update 3 V18.0.0.3 Reproducible Workaround required
V19 V19 V19.0.0.0+ Reproducible Documented workaround in manual section 4.2
V19 Update 1 (planned) V19 Update 1 (planned) — Under review Siemens support ticket pending

Configuration flags that influence the behaviour:

  • Use project default for unknown users (TIA Portal V19 project properties, Runtime settings > User administration > Default language fallback): when enabled, the project default replaces 1033 for users with HmiLanguageId = 0. It does not help when HmiLanguageId = 1033.
  • Use OS display language as fallback (Runtime settings > Languages & fonts): when enabled, the OS display language of the HMI client is used when neither the user nor the project default provides a locale. It can mask the issue if the OS is in Dutch, but it cannot be relied on for deterministic language assignment.
  • User object's HmiLanguageId in the user administration: the direct cause. The value persists across export/import, Openness API, and CSV import.

Primary Solution: @UserName-Triggered Script

The supported and Siemens-recommended workaround is to re-apply the desired language from a global JavaScript function that is triggered automatically when the @UserName system tag changes. The trigger is configured once in the project tree; the script handles all users.

Step 1: Create the global script

  1. In the TIA Portal project tree, right-click Scripts and select Add new script > JavaScript.
  2. Name the script UserChange_LanguageOverride.
  3. Open the script and paste the following code:
// UserChange_LanguageOverride
// Triggered by the @UserName system tag on change
// Re-applies the configured language for the logged-in user

function UserChange_LanguageOverride() {
    const userName = Tags("System").Read("@UserName");
    if (!userName) {
        // Logoff detected; do not change the language
        return;
    }

    // Map each user to its required LCID.
    // Add or remove entries to match the project user list.
    const userLanguageMap = {
        "Operator":    1043,  // nl-NL Dutch
        "Admin":       1031,  // de-DE German
        "Maintenance": 1033,  // en-US English
        "Service":     1036,  // fr-FR French
        "Quality":     1040,  // it-IT Italian
        "Engineer":    1031,  // de-DE German
        "Supervisor":  1043   // nl-NL Dutch
    };

    let targetLCID = userLanguageMap[userName];

    // Fallback: project default (Dutch in this example)
    if (targetLCID === undefined) {
        targetLCID = 1043;
    }

    // Apply only if different to avoid an unnecessary MLT rebuild
    if (HMIRuntime.Language !== targetLCID) {
        HMIRuntime.Language = targetLCID;
        HMIRuntime.Trace("Language override applied: user=" + userName + " LCID=" + targetLCID);
    }
}

Step 2: Configure the trigger

  1. Right-click the UserChange_LanguageOverride script in the project tree and select Properties > Triggers.
  2. Click Add and select Tag trigger.
  3. In the tag picker, expand System and select @UserName.
  4. Set the trigger condition to On change. This fires the script whenever the active user changes (login, logoff, user switch).
  5. Confirm with OK and compile the project.

Step 3: Verify the trigger fires

  1. Download the project to the Unified Panel or to Unified PC Runtime.
  2. Start the Runtime.
  3. In the HMI RT trace viewer, perform a script-driven logon. Confirm that the UserChange_LanguageOverride function is executed and that HMIRuntime.Language ends up at the mapped LCID.

The script runs synchronously with the user change event, so by the time the first screen paint happens, HMIRuntime.Language is already at the correct value. There is no flicker from English back to the desired language.

Alternative Solutions

Solution 2: Per-User Language Assignment in the User Administration

If the operator population is small and the language map is static, the cleanest fix is to set HmiLanguageId directly on each user in TIA Portal.

  1. Open Security > Users and Roles > Users in the project tree.
  2. Select the user (e.g., Operator) and open Properties.
  3. Under User language, select the desired locale from the dropdown. The dropdown lists every Runtime language that is enabled under Project tree > Runtime settings > Languages & fonts.
  4. Repeat for every user. The HmiLanguageId is now set correctly and the script workaround is no longer required.

This is the most robust solution and should be the first choice if you have a static, fully-managed user list. It does not help when users are imported dynamically or when the language must be assigned based on something other than the username (e.g., a tag value, a shift code, or a plant area).

Solution 3: Centralised Mapping in a Script Library

For projects with many users or with a language that must be derived from a Runtime variable, centralise the mapping in a global script and call it from any logon point. The map can be loaded from a tag, a CSV, or a database via the HMI's SQL interface.

// LanguageConfig.js
// Imported by other scripts; returns the LCID for a given user
export function GetLCIDForUser(userName) {
    // Priority: tag-based override > static map > project default
    const overrideTag = Tags("Configuration").Read("LanguageOverride_" + userName);
    if (overrideTag > 0) {
        return overrideTag;
    }

    const staticMap = {
        "Operator":    1043,
        "Admin":       1031,
        "Maintenance": 1033
    };

    return staticMap[userName] || 1043; // project default
}

The logon script imports this helper and applies the result:

import * as LangConfig from "LanguageConfig";

function LoginAndApplyLanguage(user, password) {
    HMIRuntime.Logon(user, password);
    const lcid = LangConfig.GetLCIDForUser(user);
    HMIRuntime.Language = lcid;
}

This pattern keeps the language map in a single place and makes it easy to extend (e.g., reading the language from an MES tag or from a shift roster).

JavaScript Code Library

The following scripts cover every common scenario encountered in WinCC Unified projects.

1. Per-User Static Map (most common)

function UserChange_LanguageOverride() {
    const userName = Tags("System").Read("@UserName");
    if (!userName) return;

    const map = {
        "Operator":    1043,
        "Admin":       1031,
        "Maintenance": 1033,
        "Service":     1036
    };

    const target = map[userName] || 1043;
    if (HMIRuntime.Language !== target) {
        HMIRuntime.Language = target;
    }
}

2. Role-Based Language Assignment

function RoleBasedLanguage() {
    const role = Tags("System").Read("@CurrentUserRole");
    const roleMap = {
        "Operator":      1043,
        "Administrator": 1031,
        "Engineer":      1031
    };
    HMIRuntime.Language = roleMap[role] || 1043;
}

3. Plant-Area-Based Language (reads an HMI tag)

function PlantAreaLanguage() {
    const area = Tags("Plant").Read("CurrentArea");
    const areaMap = {
        "AreaA": 1043,  // Dutch
        "AreaB": 1031,  // German
        "AreaC": 1033   // English
    };
    HMIRuntime.Language = areaMap[area] || 1043;
}

4. MLT Cycle on Logoff (reset to default)

function ResetToProjectDefault() {
    HMIRuntime.Language = 1043;  // Project default
    HMIRuntime.Trace("Language reset to project default on logoff");
}

5. Read-Only Diagnostic Script

function DiagnoseLanguage() {
    const user = Tags("System").Read("@UserName");
    const lang = HMIRuntime.Language;
    HMIRuntime.Trace("User: " + user + " | Language: " + lang);
}

LCID Reference Table

The HMIRuntime.Language property and the @Language system tag use Windows LCIDs. The following values are the most common locales used in WinCC Unified projects. Add a value to the project under Runtime settings > Languages & fonts before referencing it in a script; the Runtime only accepts LCIDs of languages that are enabled in the project.

LCID Locale Language Country/Region
1028 zh-TW Chinese Taiwan
1029 cs-CZ Czech Czechia
1030 da-DK Danish Denmark
1031 de-DE German Germany
1031 de-AT German Austria
1031 de-CH German Switzerland
1032 el-GR Greek Greece
1033 en-US English United States
1034 es-ES Spanish Spain
1036 fr-FR French France
1040 it-IT Italian Italy
1043 nl-NL Dutch Netherlands
1043 nl-BE Dutch Belgium
1044 nb-NO Norwegian (Bokmal) Norway
1045 pl-PL Polish Poland
1046 pt-BR Portuguese Brazil
1049 ru-RU Russian Russia
1053 sv-SE Swedish Sweden
1054 th-TH Thai Thailand
1055 tr-TR Turkish Turkey
2052 zh-CN Chinese Mainland China
2057 en-GB English United Kingdom
2070 pt-PT Portuguese Portugal
3082 es-MX Spanish Mexico
4108 fr-CH French Switzerland

Only the LCIDs corresponding to languages enabled in Runtime settings > Languages & fonts are accepted by the Runtime. Assigning an LCID that is not in the project will result in a Trace entry and the value will be ignored (Runtime falls back to the project default).

Verification & Commissioning Steps

Run the following checks in order to confirm the fix is working:

  1. Compile and download the project. Confirm that the script is included in the runtime build (no compile errors in the script editor).
  2. Open the RT trace viewer on the HMI device (Start > HMI RT > Trace Viewer, or via the WinCC Unified diagnostic page at https://<device-ip>/diagnostics in PC Runtime).
  3. Trigger a script login by clicking a button wired to HMIRuntime.Logon("Operator", "1234"). Watch the trace for the entry UserChange_LanguageOverride: Language override applied: user=Operator LCID=1043.
  4. Verify @Language. In the same trace session, confirm that the @Language system tag reads 1043 (Dutch) after the login completes.
  5. Verify screen text. Inspect a screen that contains multilingual text fields, alarm text, or button captions. All entries should display in Dutch.
  6. Test the logoff path. Click the logoff button and confirm the project default language remains. If the script is also bound to the logoff event (e.g., via a separate tag trigger on @UserName changing to empty), confirm that the fallback return is taken and the language is not overwritten.
  7. Test multiple users. Log in as Admin (German), Maintenance (English), Service (French), and Quality (Italian) in sequence. Each login must switch the language to the mapped LCID and the screen text must update immediately.
  8. Test SSO scenarios. If the project uses Simatic Logon or a third-party SSO, perform a single sign-on. Confirm the script fires on the @UserName change and the language is applied.
  9. Test restart persistence. Restart the HMI Runtime. Confirm that the project default language is loaded on startup, that the language selector is on the project default, and that the first script-driven login applies the correct per-user language.

If any of the above steps fail, check the following:

  • The script trigger is bound to @UserName, not to @CurrentUser or to a custom tag. The system tag name is case-sensitive: @UserName with capital U and N.
  • The script is scheduled to run on On change, not on On every cycle. A cycle-based trigger will fire continuously and can mask the real cause if the language keeps resetting.
  • The Tags("System") collection is available. In some V17 builds, the system tag group is named differently; verify with Tags("@System") as a fallback.
  • The target LCID is enabled in the project. The Runtime silently ignores LCIDs that are not in Runtime settings > Languages & fonts.

Edge Cases, Limitations & Related System Tags

  1. Pre-V18 users: Users created in TIA Portal V16 or V17 may not have the HmiLanguageId property. Re-create them in V18+ or set the language explicitly via the Openness API.
  2. Openness import: When importing users via the Openness API, always set the Language property on the User object. The default constructor value is 1033 (English).
  3. UAD fragments: When exporting/importing user administration data (UAD), the HmiLanguageId is preserved as set in the source project. Verify it before importing into a project with a different default locale.
  4. ASIA users: Some Asian language LCIDs (2052 Chinese Simplified, 1041 Japanese, 1042 Korean) require additional font configuration under Languages & fonts. Without the correct font, the text renders as boxes or falls back to a partial Latin set.
  5. Right-to-left (RTL) languages: Arabic (LCID 1025) and Hebrew (LCID 1037) are supported in WinCC Unified V18+ but require explicit runtime configuration. The language override script must set the LCID, but the screen layout still respects the LTR/RTL flag of the project, not of the user.
  6. Faceplates and pop-ups: Faceplates and pop-up screens inherit the active HMIRuntime.Language. The override script applies to faceplates and pop-ups as well; no per-faceplate fix is required.
  7. Alarm and message text: The Multilingual Text (MLT) system rebuilds on language change. The override may trigger a brief flicker if the MLT cache is large; this is normal and cannot be suppressed.
  8. Audit / logging: Add HMIRuntime.Trace calls in the override script to record the user-language mapping in the trace. This is required for GMP/FDA 21 CFR Part 11 audits that must record the language displayed to the operator.
  9. Concurrent sessions: Unified PC Runtime supports multiple clients. Each client has its own @UserName and HMIRuntime.Language. The override script runs in the context of the client that triggered the user change, so concurrent sessions are isolated.
  10. Hot-reload during development: Changing the script during a live debug session requires an RT restart for the trigger to bind to the new code. The behaviour is identical to other system tag triggers.

Related system tags and API members used in this fix:

Name Type Direction Description
@UserName String Read Currently logged-in user. Updated on login, logoff, and user switch.
@Language Integer (LCID) Read Current Runtime language.
HMIRuntime.Language Integer (LCID) Read/Write Get or set the active Runtime language.
HMIRuntime.Logon(user, password) Function Call Log on a user synchronously. Triggers @UserName change.
HMIRuntime.Logoff() Function Call Log off the current user. Triggers @UserName change to empty string.
HMIRuntime.Trace(text) Function Call Write an entry to the HMI RT trace.
Tags("System") Tag collection Read Access the system tag group. Read method: Tags("System").Read("@UserName").

For the full scripting reference, open the TIA Portal Help (F1) and navigate to Visualization > WinCC Unified > Programming > Scripting > JavaScript runtime API > HMIRuntime. The Siemens Industry Online Support portal hosts the latest TIA Portal Help, WinCC Unified engineering manuals, and firmware release notes that document the language controller and the user administration properties. The V19 system manual section 4.2 ("Configuring languages") describes the @UserName-based override pattern shown in this article.

Note: Always add the language override script to a global script that is bound to the @UserName tag trigger. Do not bind the script to a screen-local tag trigger; screen-local triggers fire only when the screen is active and the script will not run during the login transition.
Note: The project default language is consulted only when the user object's HmiLanguageId is 0 (undefined). Once a non-zero value is set, the project default is bypassed. To reset a user to the project default, clear the User language field in the user administration properties and re-download the project.

Frequently Asked Questions

Why does the Runtime switch to English (1033) when I call HMIRuntime.Logon() in a WinCC Unified script?

The user object loaded by HMIRuntime.Logon() carries its own HmiLanguageId property. If the property is 1033 (English) or 0 (undefined, falling back to English), the Runtime language controller overwrites HMIRuntime.Language with that value. The project default is only consulted when the user object's language is 0. To restore the project default, bind a global script to the @UserName tag trigger and re-apply the correct LCID inside the script.

Which LCID should I use for Dutch in HMIRuntime.Language?

Use 1043 (nl-NL) for Dutch in the Netherlands and 1043 (nl-BE) for Dutch in Belgium; the Runtime treats both as 1043. The value must also be enabled under Project tree > Runtime settings > Languages & fonts; otherwise the Runtime silently ignores the assignment and falls back to the project default.

How do I trigger a script when the user changes in WinCC Unified?

Add a tag trigger to the global script. Select the @UserName system tag from the System tag group and set the condition to "On change". The script fires on every login, logoff, and user switch, both in panel Runtime and in PC Runtime.

Can I set HMIRuntime.Language before calling HMIRuntime.Logon()?

Yes, but the value will be overwritten by the user object's HmiLanguageId immediately after the logon completes. The recommended pattern is to set HMIRuntime.Language inside a script that is triggered by @UserName changing, so the override runs after the user change and is the last writer to the property.

Does the language override work on Unified Comfort Panels and on Unified PC Runtime?

Yes. The HMIRuntime.Language property, the @UserName and @Language system tags, and the tag-triggered global scripts are available on all Unified Runtime targets: Unified Comfort Panels (MTP700/1000/1200/1500/1900), Unified Panels (IPC227G/277G, Nanopanel, and the new Unified Comfort range), and Unified PC Runtime on Windows 10/11 IoT Enterprise LTSC 2019/2021.

Back to blog