digitalartlab / expo-plugin-localization

Native language switching in your Expo app
https://www.npmjs.com/package/@digitalartlab/expo-plugin-localization
GNU Lesser General Public License v3.0
14 stars 0 forks source link

Build input file cannot be found: '/Users/expo/workingdir/build/ios/en.lproj/Localizable.strings' #20

Open xdmx opened 4 months ago

xdmx commented 4 months ago

First of all, thank you for this plugin. I wish Expo had something native in their localization to support for this.

Using expo 51 (not with the new arch), I've added the package and updated the app.config.js:

    plugins: [
      'expo-localization',
      'expo-notifications',
      'expo-router',
      [
        '@digitalartlab/expo-plugin-localization',
        {
          locales: ['en']
        }
      ]
  ]

But then when I try to build it through EAS I get:

❌  error: Build input file cannot be found: '/Users/expo/workingdir/build/ios/en.lproj/Localizable.strings'. Did you forget to declare this file as an output of a script phase or custom build rule which produces it? (in target 'TestApp' from project 'TestApp')

› Copying   ios/TestApp/Supporting/Expo.plist ➜ ./Expo.plist

▸ ** ARCHIVE FAILED **

▸ The following build commands failed:

▸   CopyStringsFile /Users/expo/Library/Developer/Xcode/DerivedData/TestApp-fteywkedawsmkhasrzszfbvaytdt/Build/Intermediates.noindex/ArchiveIntermediates/TestApp/InstallationBuildProductsLocation/Applications/TestApp.app/en.lproj/Localizable.strings /Users/expo/workingdir/build/ios/en.lproj/Localizable.strings (in target 'TestApp' from project 'TestApp')

▸ (1 failure)

** ARCHIVE FAILED **

Android works without issues. Any thoughts on what could be the reason?

ThijmenDeValk commented 3 months ago

Hi @xdmx! I just released v3.0.0 with support for SDK 51, and ran it through some tests with both local builds and EAS Build. If you have some time, I'd love to hear if the problem is now solved for you too.

Just as a reminder: please make sure to use the Expo Managed Workflow, or run npx expo prebuild --clean when changing the plugin settings.

bitcrumb commented 1 week ago

I'm also getting the same errors after following the installation guide:

› Copying   ios/nl.lproj/Localizable.strings ➜ nl.lproj/Localizable.strings

❌  error: Build input file cannot be found: '/Users/C8V3Q5/Developer/Projects/xxx/apps/xxx-app/ios/nl.lproj/Localizable.strings'. Did you forget to declare this file as an output of a script phase or custom build rule which produces it? (in target 'Xxx' from project 'Xxx')

The files are getting correctly created at apps/xxx-app/ios/Resources:

Screenshot 2024-10-21 at 15 08 29

However, the "Copying" phase seems to look for them in the wrong place (see log above where it doesn't reference the Resources folder).

Also, when opening up Xcode I can see the following:

Screenshot 2024-10-21 at 15 09 44 Screenshot 2024-10-21 at 15 09 56

I have the impression that whatever gets added to the project file is added with the wrong path?

ThijmenDeValk commented 1 week ago

@bitcrumb I think you're right on the money. I remember that issue from months ago, but hadn't seen it pop up anymore in recent versions. So I'll have to dive in a bit more. Just to confirm: are you on v3.0.0 for this plugin and Expo SDK 51?

bitcrumb commented 1 week ago

I'm using Expo 51.0.32 at the moment and indeed 3.0.0 of this plugin.

Also wondering if you can't just simplify things by extending the withInfoPlist implementation like this (untested):

const withNativeLocaleSwitching: ConfigPlugin<{ locales?: string[] }> = (
  config,
  { locales = ['en'] },
) => {
  config = withInfoPlist(config, (config) => {
    config.modResults['LOCALES_SUPPORTED'] = locales.join(',');
    config.modResults['CFBundleAllowMixedLocalizations'] = true;
    config.modResults['CFBundleLocalizations'] = locales;
    config.modResults['CFBundleDevelopmentRegion'] = 'en';
    return config;
  });

I noticed you have an issue open regarding this. You might be able to fix two issues at a time this way 😉? It would totally eliminate the need for Localized.strings files and updating the Xcode project file (which is cumbersome and error prone I can imagine).

I did try the approach mentioned on the linked StackOverflow thread in that issue and it does seem to work!

So maybe you can easily test this too with the above changes to the plugin?

Thanks in advance 🙏🏻

ThijmenDeValk commented 1 week ago

@bitcrumb I just published a beta version that uses CFBundleLocalizations. Your code was basically spot on, nice one 😄 Can you check that it fixes the issue for you? You will probably have to rerun prebuild to clear out the mismatched references in the iOS folder, but after that it should work (fingers crossed).

You can install it by running npm i @digitalartlab/expo-plugin-localization@3.1.0-beta.0.

bitcrumb commented 1 week ago

I'll try to have a look today! If that doesn't work out I might have to set a reminder, since I am leaving for a one-week holiday this weekend.

Thx for the effort already!

bitcrumb commented 1 week ago

Tried it out, but for some reason it is not working. I can see it gets added to the Info.plist, but nothing is shown in the app preferences pane.

bitcrumb commented 1 week ago

I think we might maybe be misinterpreting what CFBundleLocalizations actually mean. ChatGPT indicates that it is not what I think it is :P


The CFBundleLocalizations key in Info.plist is another way to support multiple localizations in your iOS app, though it’s a bit different in purpose. It allows you to declare the languages your app supports without requiring the OS to match the user’s device language exactly. Here’s how it works and when to use it:

What CFBundleLocalizations Does

CFBundleLocalizations is an array of language codes (like en, fr, de) that tells the system which localizations your app includes, even if the user’s device language isn’t one of them. It effectively provides a fallback mechanism for languages.

When to Use CFBundleLocalizations

•   Limited Localizations: If you only have a few localizations and want to provide a consistent fallback language (e.g., showing English content for unsupported locales).
•   Avoid Localizable.strings Management for Fallbacks: It’s useful when you don’t want to manage complex fallbacks for missing languages within Localizable.strings.

Limitations of CFBundleLocalizations

It doesn’t localize the UI strings or manage the Localizable.strings content itself—it just sets the languages the app supports. For text within the app, you still need to use Localizable.strings for full translations or use Info.plist localization as mentioned above.

ThijmenDeValk commented 5 days ago

I have noticed iOS is super finicky with getting the localizations to show up, even though they're configured correctly. While testing, I kept getting "the ghost of Spanish past" to appear in the list, even though it wasn't in my config anymore. Required me to try a different simulator and then it finally worked.

So... not to throw a "works on my machine" out there, but... worked on both my device and in simulators? 😅