Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature Request]: Use placeholder text for the continue button interaction #5779

Open
BenHenning opened this issue Mar 25, 2025 · 5 comments
Assignees
Labels
enhancement End user-perceivable enhancements. good first issue This item is good for new contributors to make their pull request. Impact: Medium Moderate perceived user impact (non-blocking bugs and general improvements). Work: Medium The means to find the solution is clear, but it isn't at good-first-issue level yet.

Comments

@BenHenning
Copy link
Member

Is your feature request related to a problem? Please describe.

NB: we also need to update the continue button to display the placeholder.

Originally posted by @BenHenning in #34

Without this fix in place, we encounter issues like #5743.

Describe the solution you'd like

We need to use the correctly translated placeholder text for the continue button text and only fall back to 'Continue' if there is no placeholder text present.

Describe alternatives you've considered

No response

Additional context

This will require changes to the test lesson: suggest adding a new state with placeholder continue text that has translations for each supported Oppia Android language. English & other languages should be tested using this lesson with automated tests.

@BenHenning BenHenning added enhancement End user-perceivable enhancements. triage needed labels Mar 25, 2025
@adhiamboperes adhiamboperes added Impact: Medium Moderate perceived user impact (non-blocking bugs and general improvements). Work: Medium The means to find the solution is clear, but it isn't at good-first-issue level yet. and removed triage needed labels Mar 25, 2025
@BenHenning
Copy link
Member Author

Code locations that will require changes:

Useful reference:

private fun deriveHintText(interaction: Interaction): CharSequence {
(shows how to retrieve localized customization text, but in this case for the 'TextInput' interaction type).

@BenHenning
Copy link
Member Author

@adhiamboperes I suspect that this has enough information to be considered a starter issue, WDYT?

@adhiamboperes
Copy link
Collaborator

@BenHenning, sounds good.

@adhiamboperes adhiamboperes added the good first issue This item is good for new contributors to make their pull request. label Mar 25, 2025
@shkshreyas
Copy link

Solution for Continue Button Placeholder Translation Issue

changes to files:

1. Update ContinueInteractionViewModel.kt

First, we need to modify the ContinueInteractionViewModel to retrieve the button text from customization arguments or fall back to the default string:

// ... existing code ...
class ContinueInteractionViewModel private constructor(
  interaction: Interaction,
  private val htmlParserFactory: HtmlParser.Factory,
  private val resourceBucketName: String,
  private val entityType: String,
  private val explorationId: String,
  private val context: Context
) : StateItemViewModel(ViewType.CONTINUE_INTERACTION) {
  
  val buttonText: CharSequence = deriveButtonText(interaction)
  
  // ... existing code ...
  
  private fun deriveButtonText(interaction: Interaction): CharSequence {
    val customizationArgs = interaction.customizationArgsMap["buttonText"]
    return if (customizationArgs != null && customizationArgs.hasSubtitledUnicode()) {
      val contentId = customizationArgs.subtitledUnicode.contentId
      val html = customizationArgs.subtitledUnicode.unicodeStr
      val entityId = explorationId
      htmlParserFactory.create(
        resourceBucketName, entityType, entityId, /* imageCenterAlign= */ true, 
        /* gcsPrefix= */ null, /* imageDownloadUrlTemplate= */ null, 
        /* customOppiaTagActionListener= */ null
      ).parseOppiaHtml(html, contentId)
    } else {
      context.getString(R.string.state_continue_button)
    }
  }
  
  // ... existing code ...
}

2. Update continue_interaction_item.xml

Next, we need to update the layout to use the buttonText from the ViewModel:

<!-- ... existing code ... -->
<Button
  android:id="@+id/continue_button"
  style="@style/StateButtonActive"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:layout_marginTop="12dp"
  android:background="@drawable/state_button_primary_background"
  android:minHeight="48dp"
  android:text="@{viewModel.buttonText}"
  android:textAllCaps="true"
  android:textColor="@color/white"
  android:textSize="14sp"
  app:layout_constraintBottom_toBottomOf="parent"
  app:layout_constraintStart_toStartOf="parent"
  app:layout_constraintTop_toBottomOf="@id/interaction_container" />
<!-- ... existing code ... -->

3. Update test_exp_id_2.textproto

Now we need to add a new state with translated button text:

// ... existing code ...
states {
  key: "ContinueWithCustomText"
  value {
    name: "ContinueWithCustomText"
    recorded_voiceovers {
      key: "content"
      value {
      }
    }
    recorded_voiceovers {
      key: "default_outcome"
      value {
      }
    }
    content {
      html: "<p>This state demonstrates a continue button with custom translated text.</p>"
      content_id: "content"
    }
    written_translations {
      key: "content"
      value {
        translation_mapping {
          key: "pt"
          value {
            html: "<p>Este estado demonstra um botão de continuação com texto traduzido personalizado.</p>"
          }
        }
        translation_mapping {
          key: "ar"
          value {
            html: "<p>توضح هذه الحالة زر استمرار بنص مترجم مخصص.</p>"
          }
        }
        translation_mapping {
          key: "sw"
          value {
            html: "<p>Hali hii inaonyesha kitufe cha kuendelea na maandishi yaliyotafsiriwa.</p>"
          }
        }
      }
    }
    written_translations {
      key: "default_outcome"
      value {
        translation_mapping {
          key: "pt"
          value {
            html: "Continuando para a próxima etapa."
          }
        }
        translation_mapping {
          key: "ar"
          value {
            html: "الانتقال إلى الخطوة التالية."
          }
        }
        translation_mapping {
          key: "sw"
          value {
            html: "Kuendelea hadi hatua inayofuata."
          }
        }
      }
    }
    written_translations {
      key: "ca_button_text_0"
      value {
        translation_mapping {
          key: "pt"
          value {
            html: "Continuar"
          }
        }
        translation_mapping {
          key: "ar"
          value {
            html: "استمر"
          }
        }
        translation_mapping {
          key: "sw"
          value {
            html: "Endelea"
          }
        }
      }
    }
    interaction {
      id: "Continue"
      default_outcome {
        dest_state_name: "Fractions"
        feedback {
          html: "Continuing to the next step."
          content_id: "default_outcome"
        }
        labelled_as_correct: true
      }
      customization_args {
        key: "buttonText"
        value {
          custom_schema_value {
            subtitled_unicode {
              unicode_str: "Continue"
              content_id: "ca_button_text_0"
            }
          }
        }
      }
    }
    linked_skill_id: "test_skill_id_0"
  }
}
// ... existing code ...

Also, update the existing Continue state to point to our new state:

// ... existing code ...
states {
  key: "Continue"
  value {
    // ... existing code ...
    interaction {
      id: "Continue"
      default_outcome {
        dest_state_name: "ContinueWithCustomText"
        feedback {
          html: "Continuing onward."
          content_id: "default_outcome"
        }
        labelled_as_correct: true
      }
      // Remove the buttonText customization arg if it exists
    }
    // ... existing code ...
  }
}
// ... existing code ...

4. Add Tests in StateFragmentTest.kt

Finally, add tests to verify the button text in different languages:

// ... existing code ...

@Test
fun testStateFragment_loadExp_continueWithCustomText_englishLocale_showsEnglishButtonText() {
  launchForExploration(TEST_EXPLORATION_ID_2).use {
    // Navigate to the Continue state
    onView(withId(R.id.continue_button)).perform(click())
    
    // Verify we're on the ContinueWithCustomText state
    onView(withId(R.id.content_text_view))
      .check(matches(withText(containsString("demonstrates a continue button"))))
    
    // Verify the button text is in English
    onView(withId(R.id.continue_button))
      .check(matches(withText("CONTINUE")))
  }
}

@Test
fun testStateFragment_loadExp_continueWithCustomText_portugueseLocale_showsPortugueseButtonText() {
  activityTestRule.launchActivity(createExplorationActivityIntent(TEST_EXPLORATION_ID_2))
  
  // Set locale to Portuguese
  onView(isRoot()).perform(configureLocale("pt"))
  
  // Navigate to the Continue state
  onView(withId(R.id.continue_button)).perform(click())
  
  // Verify the button text is in Portuguese
  onView(withId(R.id.continue_button))
    .check(matches(withText("CONTINUAR")))
}

@Test
fun testStateFragment_loadExp_continueWithCustomText_arabicLocale_showsArabicButtonText() {
  activityTestRule.launchActivity(createExplorationActivityIntent(TEST_EXPLORATION_ID_2))
  
  // Set locale to Arabic
  onView(isRoot()).perform(configureLocale("ar"))
  
  // Navigate to the Continue state
  onView(withId(R.id.continue_button)).perform(click())
  
  // Verify the button text is in Arabic
  onView(withId(R.id.continue_button))
    .check(matches(withText("استمر")))
}

@Test
fun testStateFragment_loadExp_continueWithCustomText_swahiliLocale_showsSwahiliButtonText() {
  activityTestRule.launchActivity(createExplorationActivityIntent(TEST_EXPLORATION_ID_2))
  
  // Set locale to Swahili
  onView(isRoot()).perform(configureLocale("sw"))
  
  // Navigate to the Continue state
  onView(withId(R.id.continue_button)).perform(click())
  
  // Verify the button text is in Swahili
  onView(withId(R.id.continue_button))
    .check(matches(withText("ENDELEA")))
}

// Helper method to configure locale for testing
private fun configureLocale(languageCode: String): ViewAction {
  return object : ViewAction {
    override fun getConstraints(): Matcher<View> = isRoot()
    override fun getDescription(): String = "Set locale to $languageCode"
    override fun perform(uiController: UiController, view: View) {
      val context = view.context
      val locale = Locale(languageCode)
      Locale.setDefault(locale)
      val resources = context.resources
      val configuration = resources.configuration
      configuration.setLocale(locale)
      context.createConfigurationContext(configuration)
    }
  }
}

// ... existing code ...

These changes will ensure that the Continue button displays the translated text when available, and falls back to the default "Continue" text when no translation is provided.

@adhiamboperes
Copy link
Collaborator

@shkshreyas, I have assigned you this issue.

In future, you don't need to write the code. Instead, provide a simple explanation of your proposed solution, or you can create a draft PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement End user-perceivable enhancements. good first issue This item is good for new contributors to make their pull request. Impact: Medium Moderate perceived user impact (non-blocking bugs and general improvements). Work: Medium The means to find the solution is clear, but it isn't at good-first-issue level yet.
Development

No branches or pull requests

3 participants