Understanding the Root Cause
The discrepancy usually arises because Bash and Fish handle character encoding differently by default. Bash in Ubuntu WSL relies heavily on theLANG and LC_ALL environment variables defined in your system locale. If these are not explicitly set to a UTF-8 variant, Bash may fall back to ASCII or C locale, causing special characters to display incorrectly.
Fishshell, on the other hand, generally assumes UTF-8 encoding for its input and output streams. When you switch from Fish to Bash, if the Bash session does not inherit the correct UTF-8 locale configuration, the terminal displays mojibake (garbled text). Conversely, switching from Bash to Fish might fail if Fish detects an incompatible locale setting that restricts its ability to process multi-byte characters. This inconsistency is particularly noticeable in WSL environments where the Linux distribution shares the same file system and environment as the Windows host.
Checking Current Locale Settings
Before applying fixes, verify the current state of your locale settings. Open your terminal and run the following command in both Bash and Fish:locale
Look for the values of LANG, LC_CTYPE, and LC_ALL. In a properly configured UTF-8 environment, these should point to something like en_US.UTF-8 or C.UTF-8. If you see C or POSIX, your system is not using UTF-8, which explains the encoding errors. Note that Fish may report slightly different behavior if it overrides certain locale variables internally, so comparing the output in both shells is crucial.
Configuring System-Wide Locale
The most robust solution is to ensure the Ubuntu WSL distribution itself is configured with a UTF-8 locale. This prevents Bash from ever falling back to a non-UTF-8 mode. You can check available locales by running:locale -a
If en_US.UTF-8 or another UTF-8 variant is missing, you need to generate it. First, edit the locale configuration file:
sudo nano /etc/default/locale
Ensure the file contains the following line, replacing en_US with your preferred language code if necessary:
LANG=en_US.UTF-8
Next, regenerate the locales to ensure the system has the necessary data files:
sudo locale-gen
After this step, restart your WSL instance completely by closing all terminals and running wsl --shutdown in PowerShell or Command Prompt, then reopening the terminal. This ensures that new sessions start with the correct locale environment.
Aligning Fishshell Configuration
While Fish defaults to UTF-8, it is good practice to explicitly set the locale within Fish to match your system configuration. Edit your Fish configuration file located at~/.config/fish/config.fish. Add the following lines to enforce UTF-8:
set -x LANG en_US.UTF-8
set -x LC_ALL en_US.UTF-8
This ensures that even if the parent shell (Bash) has misconfigured locale variables, Fish will override them correctly. Save the file and restart Fish. If you are using Fish version 3.0 or later, you can also use the fish_user_paths function to manage environment variables more cleanly, but explicit set -x commands are universally compatible.
Windows Terminal Profile Adjustments
Since you are using WSL, your terminal emulator plays a significant role in how encoding is handled. Windows Terminal automatically detects the encoding for WSL profiles, but sometimes manual intervention is needed if issues persist. Open your Windows Terminal settings by clicking the dropdown arrow next to the tab bar and selecting "Settings". Navigate to the profile associated with your Ubuntu WSL installation. Under the "Advanced" section, ensure that "Encoding" is set to "Auto-detect" or explicitly to "UTF-8". Avoid setting it to "Western European" or other legacy encodings, as this forces the terminal to interpret bytes incorrectly before they reach the shell. If you have multiple profiles, ensure consistency across all Linux-based profiles to avoid confusion when switching contexts. For users experiencing broader connectivity or package management issues in WSL Ubuntu, such as certificate verification failures during repository additions, resolving those underlying system integrity issues can also indirectly affect shell stability. See our guide on Resolving Certificate Verification Failure in WSL Ubuntu for add-apt-repository if you encounter related system-level errors.Verifying the Fix
After applying these changes, test the transition between shells. Open a Bash terminal and runecho $LANG. It should return en_US.UTF-8. Then, launch Fish and run the same command. It should also return en_US.UTF-8. Try typing special characters like é, ñ, or emoji in both shells. They should display correctly without corruption.
If you still experience issues, consider checking if any custom scripts in your .bashrc or .fish are overriding locale variables. Comment out suspicious lines and reload the configuration files using source ~/.bashrc or source ~/.config/fish/config.fish. For users needing to restore their WSL environment from scratch due to deep-seated configuration corruption, importing a previously exported distro might be a viable last resort. Learn more about Importing Previously Exported WSL Distro if you need to rebuild your environment.
Frequently Asked Questions
Why does my terminal show question marks instead of special characters?
This indicates that the terminal font does not support the specific Unicode characters you are trying to display, or the locale is set to a single-byte encoding. Ensure your Windows Terminal font supports Unicode and that your WSL locale is set to UTF-8.
Can I use a different locale like fr_FR.UTF-8?
Yes, you can use any valid UTF-8 locale supported by your Ubuntu distribution. Just replace en_US with fr_FR in the /etc/default/locale file and run sudo locale-gen to generate the necessary data files.
Does Fishshell ignore Bash's locale settings?
Fish reads its own environment variables independently. If you set LANG in .bashrc, it does not automatically apply to Fish unless you export it globally. Explicitly setting it in config.fish ensures consistency regardless of the parent shell.
How do I reset my WSL locale to defaults?
To reset, remove custom entries from /etc/default/locale and delete any explicit set -x LANG commands from your Fish config. Run sudo dpkg-reconfigure locales to restore the system default, which is usually C.UTF-8.
Is WSLg relevant to encoding issues?
WSLg handles graphical application integration and does not directly influence terminal character encoding. Encoding issues are strictly related to locale settings and terminal emulator configurations, so WSLg status is unrelated to this problem.