Please see below my solution. It's not ideal, because it breaks pagination a bit, but it's feasible for our use case, as we don't have too many new post activities.
// Filter the activity feed by the language:
// 1. buffer the activity entry output...
add_action('bp_before_activity_entry', function () {
ob_start();
});
// 2. clean the output if the activity is the post activity and languages don't match,
// flush otherwise.
add_action('bp_after_activity_entry', function () {
$get_lang = $_GET['lang'];
$language_code = get_activity_post_language_code();
if ( $language_code && $get_lang && $language_code !== $get_lang ) {
ob_end_clean();
} else {
ob_end_flush();
}
});
function get_activity_post_language_code() {
if ( ! bp_get_activity_secondary_item_id() ) {
return false;
}
$language_details = apply_filters( 'wpml_post_language_details', NULL, bp_get_activity_secondary_item_id() );
if ( ! $language_details ) {
return false;
}
return $language_details['language_code'];
}