This commit is contained in:
lx
2026-07-06 14:01:11 -04:00
commit c4f97d729d
16468 changed files with 935321 additions and 0 deletions
@@ -0,0 +1,193 @@
local CorePackages = game:GetService("CorePackages")
local Roact = require(CorePackages.Roact)
local Modalifier = require(script.Parent.Modalifier)
local Dropdown = Roact.Component:extend("Dropdown")
function Dropdown:init()
self.state = {
Open = false,
Hovered = false,
}
end
function Dropdown:render()
local listChildren = {
Layout = Roact.createElement("UIListLayout", {
SortOrder = Enum.SortOrder.LayoutOrder,
}),
}
for index, listItem in ipairs(self.props.ListItems) do
listChildren["ListObject"..index] = Roact.createElement("Frame", {
Size = UDim2.new(1, 0, 0, self.props.ListItemHeight),
LayoutOrder = index,
BorderSizePixel = 0,
BackgroundTransparency = 1,
}, {
Padding = Roact.createElement("UIPadding", {
PaddingBottom = UDim.new(0, 4),
}),
Button = Roact.createElement("TextButton", {
BorderSizePixel = 0,
Size = UDim2.new(1, 0, 1, 0),
TextColor3 = self.props.TextColor3,
Text = "",
BackgroundColor3 = self.props.BackgroundColor3,
[Roact.Event.Activated] = function()
listItem.OnActivated()
self:setState({
Open = false,
})
end,
}, {
Padding = Roact.createElement("UIPadding", {
PaddingLeft = UDim.new(0, 4),
}),
Text = Roact.createElement("TextLabel", {
BackgroundTransparency = 1,
TextColor3 = self.props.TextColor3,
Size = UDim2.new(1, 0, 1, 0),
Text = listItem.Text,
TextXAlignment = Enum.TextXAlignment.Left,
}),
}),
})
end
local visibleChildren
if self.state.Open then
visibleChildren = {
Button = Roact.createElement("TextButton", {
Size = UDim2.new(1, 0, 1, 0),
BorderColor3 = self.props.BorderColor3,
AutoButtonColor = false,
BackgroundTransparency = 0,
Text = "",
BackgroundColor3 = self.props.ButtonDownColor3,
TextXAlignment = Enum.TextXAlignment.Left,
[Roact.Event.Activated] = function()
self:setState({
Open = false,
})
end,
-- Empty functions here work around bug-147 in Roact
[Roact.Event.InputBegan] = function()
end,
[Roact.Event.InputEnded] = function()
end,
}, {
Padding = Roact.createElement("UIPadding", {
PaddingLeft = UDim.new(0, 4),
}),
TextLabel = Roact.createElement("TextLabel", {
Size = UDim2.new(1, 0, 1, 0),
TextColor3 = self.props.TextColor3,
BackgroundTransparency = 1,
BorderSizePixel = 0,
TextXAlignment = Enum.TextXAlignment.Left,
Text = self.props.CurrentText,
}),
Arrow = Roact.createElement("ImageLabel", {
Position = UDim2.new(1, -15, 0.5, 0),
AnchorPoint = Vector2.new(0.5, 0.5),
Size = UDim2.new(0, 5, 0, 3),
BorderSizePixel = 0,
BackgroundTransparency = 1,
Image = "rbxasset://textures/menuDownArrow.png",
}),
}),
Modalifier = Roact.createElement(Modalifier, {
Window = self.props.Window,
OnClosed = function()
self:setState({
Open = false,
})
end,
Render = function(position)
return Roact.createElement("Frame", {
Position = UDim2.new(0, position.X, 0, position.Y + self.props.ListItemHeight),
Size = UDim2.new(0, 160, 0, #(self.props.ListItems) * self.props.ListItemHeight),
BackgroundTransparency = 0,
BackgroundColor3 = self.props.BackgroundColor3,
BorderColor3 = self.props.BorderColor3,
}, listChildren)
end,
}),
}
else
visibleChildren = {
Button = Roact.createElement("TextButton", {
Size = UDim2.new(1, 0, 1, 0),
BorderColor3 = self.props.BorderColor3,
AutoButtonColor = false,
BackgroundTransparency = 0,
BackgroundColor3 = self.state.Hovered and self.props.ButtonHoverColor3 or self.props.BackgroundColor3,
Text = "",
TextXAlignment = Enum.TextXAlignment.Left,
[Roact.Event.Activated] = function()
self:setState({
Open = true,
Hovered = false,
})
end,
[Roact.Event.InputBegan] = function(gui, input)
if input.UserInputType == Enum.UserInputType.MouseMovement then
self:setState({
Hovered = true,
})
end
end,
[Roact.Event.InputEnded] = function(gui, input)
if input.UserInputType == Enum.UserInputType.MouseMovement then
self:setState({
Hovered = false,
})
end
end,
}, {
Padding = Roact.createElement("UIPadding", {
PaddingLeft = UDim.new(0, 4),
}),
TextLabel = Roact.createElement("TextLabel", {
Size = UDim2.new(1, 0, 1, 0),
TextColor3 = self.props.TextColor3,
BackgroundTransparency = 1,
BorderSizePixel = 0,
TextXAlignment = Enum.TextXAlignment.Left,
Text = self.props.CurrentText,
}),
Arrow = Roact.createElement("ImageLabel", {
Position = UDim2.new(1, -15, 0.5, 0),
AnchorPoint = Vector2.new(0.5, 0.5),
Size = UDim2.new(0, 5, 0, 3),
BorderSizePixel = 0,
BackgroundTransparency = 1,
Image = "rbxasset://textures/menuDownArrow.png",
}),
}),
}
end
return Roact.createElement("Frame", {
Size = UDim2.new(1, 0, 1, 0),
}, visibleChildren)
end
return Dropdown
@@ -0,0 +1,47 @@
local CorePackages = game:GetService("CorePackages")
local Roact = require(CorePackages.Roact)
local LocaleSelector = require(script.Parent.LocaleSelector)
local LabeledLocaleSelector = Roact.Component:extend("LabeledLocaleSelector")
function LabeledLocaleSelector:render()
return Roact.createElement("Frame", {
Size = UDim2.new(0, 300, 0, 25),
BackgroundTransparency = 1,
BorderSizePixel = 0,
LayoutOrder = self.props.LayoutOrder
}, {
Layout = Roact.createElement("UIListLayout", {
SortOrder = Enum.SortOrder.LayoutOrder,
FillDirection = Enum.FillDirection.Horizontal,
Padding = UDim.new(0, 5),
}),
LocaleIdLabel = Roact.createElement("TextLabel", {
Text = self.props.LabelText,
TextXAlignment = "Right",
TextYAlignment = "Center",
TextColor3 = self.props.TextColor3,
BackgroundTransparency = 1,
BorderSizePixel = 0,
Size = UDim2.new(0, 50, 0, 25),
LayoutOrder = 0,
}),
LocaleSelectorGroup = Roact.createElement(LocaleSelector, {
Window = self.props.Window,
Size = UDim2.new(0, 200, 0, 25),
BackgroundColor3 = self.props.BackgroundColor3,
TextColor3 = self.props.TextColor3,
BorderColor3 = self.props.BorderColor3,
ButtonHoverColor3 = self.props.ButtonHoverColor3,
ButtonDownColor3 = self.props.ButtonDownColor3,
InitialLocaleId = self.props.InitialLocaleId,
SetLocaleId = self.props.SetLocaleId,
LayoutOrder = 1,
}),
})
end
return LabeledLocaleSelector
@@ -0,0 +1,127 @@
local CorePackages = game:GetService("CorePackages")
local Roact = require(CorePackages.Roact)
local Dropdown = require(script.Parent.Dropdown)
local customMenuItemText = "(Custom)"
local localeInfos = {
{ localeId = "en-us", name = "English" },
{ localeId = "fr-fr", name = "French" },
{ localeId = "de-de", name = "German" },
{ localeId = "pt-br", name = "Portuguese (Brazil)" },
{ localeId = "es-es", name = "Spanish" },
}
local localeNameMap = {}
for _, info in ipairs(localeInfos) do
localeNameMap[info.localeId] = info.name
end
local LocaleSelector = Roact.Component:extend("LocaleSelector")
function LocaleSelector:init()
self.state = {
LocaleId = self.props.InitialLocaleId
}
self.textBoxRef = Roact.createRef()
end
local function getMenuTextForLocale(localeId)
if localeId == "" then
return customMenuItemText
end
return localeNameMap[localeId] or customMenuItemText
end
function LocaleSelector:render()
local ListItems = {}
for index, item in ipairs(localeInfos) do
ListItems[index] = {
Text = item.name,
OnActivated = function()
self:setState({
LocaleId = item.localeId,
})
end
}
end
ListItems[#localeInfos + 1] = {
Text = customMenuItemText,
OnActivated = function()
self:setState({
LocaleId = "",
})
self.textBoxRef.current:CaptureFocus()
end
}
return Roact.createElement("Frame", {
Size = self.props.Size,
BackgroundTransparency = 1.0,
}, {
Layout = Roact.createElement("UIListLayout", {
SortOrder = Enum.SortOrder.LayoutOrder,
FillDirection = Enum.FillDirection.Horizontal,
Padding = UDim.new(0, 5),
}),
LocaleNameDropdown = Roact.createElement("Frame", {
Size = UDim2.new(0, 160, 0, 25),
LayoutOrder = 1,
}, {
Dropdown = Roact.createElement(Dropdown, {
Window = self.props.Window,
BackgroundColor3 = self.props.BackgroundColor3,
TextColor3 = self.props.TextColor3,
BorderColor3 = self.props.BorderColor3,
ButtonHoverColor3 = self.props.ButtonHoverColor3,
ButtonDownColor3 = self.props.ButtonDownColor3,
CurrentText = getMenuTextForLocale(self.state.LocaleId),
ListItemHeight = 25,
ListItems = ListItems,
}),
}),
LocaleIdTextBox = Roact.createElement("Frame", {
Size = UDim2.new(0, 50, 0, 25),
BorderSizePixel = 1,
BorderColor3 = self.props.BorderColor3,
BackgroundColor3 = self.props.BackgroundColor3,
LayoutOrder = 2,
}, {
Padding = Roact.createElement("UIPadding", {
PaddingLeft = UDim.new(0, 4),
}),
TextboxInternal = Roact.createElement("TextBox", {
Size = UDim2.new(1, 0, 1, 0),
TextColor3 = self.props.TextColor3,
BorderColor3 = self.props.BorderColor3,
Text = self.state.LocaleId,
TextXAlignment = "Left",
ClearTextOnFocus = false,
BackgroundTransparency = 1,
[Roact.Ref] = self.textBoxRef,
[Roact.Event.FocusLost] = function()
self:setState({
LocaleId = self.textBoxRef.current.Text,
})
end,
})
}),
})
end
function LocaleSelector:didUpdate()
self.props.SetLocaleId(self.state.LocaleId)
end
return LocaleSelector
@@ -0,0 +1,53 @@
local CorePackages = game:GetService("CorePackages")
local Roact = require(CorePackages.Roact)
local Modalifier = Roact.Component:extend("Modalifier")
function Modalifier:init()
self.state = {
ContentAbsolutePosition = Vector2.new(0, 0),
Showing = false,
}
end
function Modalifier:render()
local visibleChildren = {}
if self.state.Showing then
visibleChildren = {
content = self.props.Render(self.state.ContentAbsolutePosition),
}
end
return Roact.createElement("Frame", {
Size = UDim2.new(1, 0, 1, 0),
BackgroundTransparency = 1,
BorderSizePixel = 0,
[Roact.Change.AbsolutePosition] = function(instance)
spawn(function()
self:setState({
ContentAbsolutePosition = instance.AbsolutePosition,
Showing = true,
})
end)
end,
}, {
Portal = Roact.createElement(Roact.Portal, {
-- Future redesign strongly suggested here: https://jira.roblox.com/browse/CLILUACORE-287
target = self.props.Window,
}, {
Curtain = Roact.createElement("TextButton", {
Size = UDim2.new(1, 0, 1, 0),
BackgroundTransparency = 1,
BorderSizePixel = 0,
Text = "",
[Roact.Event.Activated] = function()
self.props.OnClosed()
end,
}, visibleChildren),
}),
})
end
return Modalifier
@@ -0,0 +1,76 @@
local CorePackages = game:GetService("CorePackages")
local Roact = require(CorePackages.Roact)
local LabeledLocaleSelector = require(script.Parent.LabeledLocaleSelector)
local PlayerLocaleView = Roact.Component:extend("PlayerLocaleView")
local StudioEnableLuaAPIsForThemes = settings():GetFFlag("StudioEnableLuaAPIsForThemes")
local robloxLocaleLabelText = "Locale"
function PlayerLocaleView:init()
if StudioEnableLuaAPIsForThemes then
self.state = {
Theme = settings().Studio.Theme,
}
end
end
function PlayerLocaleView:render()
local TextColor3
local BorderColor3
local BackgroundColor3
local ButtonHoverColor3
local ButtonDownColor3
if StudioEnableLuaAPIsForThemes then
TextColor3 = self.state.Theme:GetColor(Enum.StudioStyleGuideColor.BrightText)
BorderColor3 = self.state.Theme:GetColor(Enum.StudioStyleGuideColor.Border)
BackgroundColor3 = self.state.Theme:GetColor(Enum.StudioStyleGuideColor.MainBackground)
ButtonHoverColor3 = self.state.Theme:GetColor(Enum.StudioStyleGuideColor.Button, Enum.StudioStyleGuideModifier.Hover)
ButtonDownColor3 = self.state.Theme:GetColor(Enum.StudioStyleGuideColor.Button, Enum.StudioStyleGuideModifier.Pressed)
else
TextColor3 = Color3.new( 0, 0, 0 )
BorderColor3 = Color3.new( 0.713726, 0.713726, 0.713726 )
BackgroundColor3 = Color3.new( 1, 1, 1 )
ButtonHoverColor3 = Color3.new( 0.894118, 0.933333, 0.996078 )
ButtonDownColor3 = Color3.new( 0.858824, 0.858824, 0.858824 )
end
return Roact.createElement("Frame", {
Size = UDim2.new(1, 0, 1, 0),
BackgroundTransparency = 0,
BackgroundColor3 = BackgroundColor3,
BorderSizePixel = 0,
}, {
Padding = Roact.createElement("UIPadding", {
PaddingTop = UDim.new(0, 5),
}),
Roblox = Roact.createElement(LabeledLocaleSelector, {
Window = self.props.Window,
LabelText = robloxLocaleLabelText,
TextColor3 = TextColor3,
BorderColor3 = BorderColor3,
BackgroundColor3 = BackgroundColor3,
ButtonHoverColor3 = ButtonHoverColor3,
ButtonDownColor3 = ButtonDownColor3,
InitialLocaleId = self.props.InitialRobloxLocaleId,
SetLocaleId = self.props.SetRobloxLocaleId,
}),
})
end
function PlayerLocaleView:didMount()
if StudioEnableLuaAPIsForThemes then
settings().Studio.ThemeChanged:Connect(
function()
self:setState({
Theme = settings().Studio.Theme,
})
end
)
end
end
return PlayerLocaleView
@@ -0,0 +1,100 @@
local runService = game:GetService("RunService")
local LocalizationService = game:GetService("LocalizationService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local CorePackages = game:GetService("CorePackages")
local enabled = runService:IsEdit()
local function createTextScraperControls(toolbar, plugin)
function getTextScraperAsset()
return LocalizationService.IsTextScraperRunning
and "rbxasset://textures/localizationUIScrapingOn.png"
or "rbxasset://textures/localizationUIScrapingOff.png"
end
local captureButton = toolbar:CreateButton(
"Text Capture",
"Enable untranslated text capture",
getTextScraperAsset()
)
local exportButton = toolbar:CreateButton(
"Export",
"Export LocalizationTables under LocalizationService to CSV files",
"rbxasset://textures/localizationExport.png"
)
local importButton = toolbar:CreateButton(
"Import",
"Import CSV files to LocalizationTables under LocalizationService",
"rbxasset://textures/localizationImport.png"
)
captureButton.Enabled = enabled
captureButton.Click:Connect(function()
if not LocalizationService.IsTextScraperRunning then
LocalizationService:StartTextScraper()
else
LocalizationService:StopTextScraper()
end
captureButton.Icon = getTextScraperAsset()
end)
exportButton.Enabled = enabled
exportButton.Click:Connect(function()
LocalizationService:PromptExportToCSVs()
end)
importButton.Enabled = enabled
importButton.Click:Connect(function()
LocalizationService:PromptImportFromCSVs()
end)
end
local function getInitialRobloxLocaleId()
local forcedLocale = LocalizationService.RobloxForcePlayModeRobloxLocaleId
if forcedLocale ~= "" then
return forcedLocale
end
return LocalizationService.RobloxLocaleId
end
local function createPlayerLocaleViewButton(toolbar, plugin)
local PlayerLocaleView = require(script.Parent.Components.PlayerLocaleView)
local Roact = require(CorePackages.Roact)
local Window = plugin:CreateDockWidgetPluginGui("LocalizationTesting",
DockWidgetPluginGuiInfo.new(Enum.InitialDockState.Left))
Window.Title = "Test Language"
local params = {
Window = Window,
SetRobloxLocaleId = function(localeId)
LocalizationService.RobloxForcePlayModeRobloxLocaleId = localeId
end,
InitialRobloxLocaleId = getInitialRobloxLocaleId(),
}
Roact.mount(Roact.createElement(PlayerLocaleView, params), Window)
Window.Enabled = false
local button = toolbar:CreateButton(
"Test Language",
"Hide/show the Localization Testing view",
"rbxasset://textures/localizationTestingIcon.png")
button.Enabled = enabled
button.Click:Connect(
function()
Window.Enabled = not Window.Enabled
end
)
end
return function(plugin)
local toolbar = plugin:CreateToolbar("Localization Tools")
createTextScraperControls(toolbar, plugin)
createPlayerLocaleViewButton(toolbar, plugin)
end
@@ -0,0 +1,30 @@
local CorePackages = game:GetService("CorePackages")
return function()
local Roact = require(CorePackages.Roact)
local Dropdown = require(script.Parent.Parent.Components.Dropdown)
it("mounts and unmounts", function()
local handle = Roact.mount(Roact.createElement(Dropdown, {
ListItems = {},
}))
Roact.unmount(handle)
end)
itFIXME("inits with an item list and includes the default value in the resulting UI", function()
local container = Instance.new("Frame")
local element = Roact.createElement(Dropdown, {
CurrentText = "Option 1 (default)",
ListItems = {
"Option 1",
"Option 2"
},
})
local handle = Roact.mount(element, container)
expect(container.Frame.button.textLabel.Text).to.equal("Option 1 (default)")
Roact.unmount(handle)
end)
end
@@ -0,0 +1,24 @@
local CorePackages = game:GetService("CorePackages")
return function()
local Roact = require(CorePackages.Roact)
local LabeledLocaleSelector = require(script.Parent.Parent.Components.LabeledLocaleSelector)
it("mounts and unmounts", function()
local element = Roact.createElement(LabeledLocaleSelector)
local handle = Roact.mount(element)
Roact.unmount(handle)
end)
it("inits with label text and displays that label text", function()
local container = Instance.new("Frame")
local element = Roact.createElement(LabeledLocaleSelector, {
LabelText = "Choose your locale"
})
local handle = Roact.mount(element, container)
expect(container.Frame.LocaleIdLabel.Text).to.equal("Choose your locale")
Roact.unmount(handle)
end)
end
@@ -0,0 +1,32 @@
local CorePackages = game:GetService("CorePackages")
local function recursivePrint(node, indent)
indent = indent or ""
for _, child in pairs(node:GetChildren()) do
print("|"..indent..tostring( child.Name ))
recursivePrint(child, indent.." ")
end
end
return function()
local Roact = require(CorePackages.Roact)
local LocaleSelector = require(script.Parent.Parent.Components.LocaleSelector)
it("mounts and unmounts", function()
local element = Roact.createElement(LocaleSelector)
local handle = Roact.mount(element)
Roact.unmount(handle)
end)
it("inits with a selected locale and displays that locale", function()
local container = Instance.new("Frame")
local element = Roact.createElement(LocaleSelector, {
InitialLocaleId = "kw-gb"
})
local handle = Roact.mount(element, container)
expect(container.Frame.LocaleIdTextBox.TextboxInternal.Text).to.equal("kw-gb")
Roact.unmount(handle)
end)
end
@@ -0,0 +1,16 @@
local CorePackages = game:GetService("CorePackages")
return function()
local Roact = require(CorePackages.Roact)
local Modalifier = require(script.Parent.Parent.Components.Modalifier)
it("mounts and unmounts and puts the curtain up", function()
local container = Instance.new("Frame")
local element = Roact.createElement(Modalifier, {
Window = container
})
local handle = Roact.mount(element)
expect(container.Curtain).to.be.ok()
Roact.unmount(handle)
end)
end
@@ -0,0 +1,13 @@
local CorePackages = game:GetService("CorePackages")
return function()
local Roact = require(CorePackages.Roact)
local PlayerLocaleView = require(script.Parent.Parent.Components.PlayerLocaleView)
itFIXME("mounts and unmounts", function()
-- With --fflags==true throws error: Studio is not a valid member of GlobalSettings
local element = Roact.createElement(PlayerLocaleView)
local handle = Roact.mount(element)
Roact.unmount(handle)
end)
end